/* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.wallet.ui; import static android.provider.Settings.ACTION_LOCKSCREEN_SETTINGS; import android.content.Intent; import android.graphics.drawable.Drawable; import android.hardware.biometrics.BiometricSourceType; import android.os.Bundle; import android.os.Handler; import android.service.quickaccesswallet.QuickAccessWalletClient; import android.service.quickaccesswallet.WalletServiceEvent; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.Window; import android.view.WindowManager; import android.widget.Toolbar; import androidx.activity.ComponentActivity; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.logging.UiEventLogger; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.settingslib.Utils; import com.android.systemui.R; import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.phone.KeyguardDismissUtil; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.policy.KeyguardStateController; import java.util.concurrent.Executor; import javax.inject.Inject; /** * Displays Wallet carousel screen inside an activity. */ public class WalletActivity extends ComponentActivity implements QuickAccessWalletClient.WalletServiceEventListener { private static final String TAG = "WalletActivity"; private final KeyguardStateController mKeyguardStateController; private final KeyguardDismissUtil mKeyguardDismissUtil; private final ActivityStarter mActivityStarter; private final Executor mExecutor; private final Handler mHandler; private final FalsingManager mFalsingManager; private FalsingCollector mFalsingCollector; private final UserTracker mUserTracker; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final StatusBarKeyguardViewManager mKeyguardViewManager; private final UiEventLogger mUiEventLogger; private KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback; private WalletScreenController mWalletScreenController; private QuickAccessWalletClient mWalletClient; private boolean mHasRegisteredListener; @Inject public WalletActivity( KeyguardStateController keyguardStateController, KeyguardDismissUtil keyguardDismissUtil, ActivityStarter activityStarter, @Background Executor executor, @Main Handler handler, FalsingManager falsingManager, FalsingCollector falsingCollector, UserTracker userTracker, KeyguardUpdateMonitor keyguardUpdateMonitor, StatusBarKeyguardViewManager keyguardViewManager, UiEventLogger uiEventLogger) { mKeyguardStateController = keyguardStateController; mKeyguardDismissUtil = keyguardDismissUtil; mActivityStarter = activityStarter; mExecutor = executor; mHandler = handler; mFalsingManager = falsingManager; mFalsingCollector = falsingCollector; mUserTracker = userTracker; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mKeyguardViewManager = keyguardViewManager; mUiEventLogger = uiEventLogger; } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.quick_access_wallet); Toolbar toolbar = findViewById(R.id.action_bar); if (toolbar != null) { setActionBar(toolbar); } getActionBar().setDisplayShowTitleEnabled(false); getActionBar().setDisplayHomeAsUpEnabled(true); getActionBar().setHomeAsUpIndicator(getHomeIndicatorDrawable()); getActionBar().setHomeActionContentDescription(R.string.accessibility_desc_close); WalletView walletView = requireViewById(R.id.wallet_view); mWalletClient = QuickAccessWalletClient.create(this, mExecutor); mWalletScreenController = new WalletScreenController( this, walletView, mWalletClient, mActivityStarter, mExecutor, mHandler, mUserTracker, mFalsingManager, mKeyguardUpdateMonitor, mKeyguardStateController, mUiEventLogger); mKeyguardUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() { @Override public void onBiometricRunningStateChanged( boolean running, BiometricSourceType biometricSourceType) { Log.d(TAG, "Biometric running state has changed."); mWalletScreenController.queryWalletCards(); } }; walletView.setFalsingCollector(mFalsingCollector); walletView.setShowWalletAppOnClickListener( v -> { if (mWalletClient.createWalletIntent() == null) { Log.w(TAG, "Unable to create wallet app intent."); return; } if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return; } if (mKeyguardStateController.isUnlocked()) { mUiEventLogger.log(WalletUiEvent.QAW_SHOW_ALL); mActivityStarter.startActivity( mWalletClient.createWalletIntent(), true); finish(); } else { mUiEventLogger.log(WalletUiEvent.QAW_UNLOCK_FROM_SHOW_ALL_BUTTON); mKeyguardDismissUtil.executeWhenUnlocked(() -> { mUiEventLogger.log(WalletUiEvent.QAW_SHOW_ALL); mActivityStarter.startActivity( mWalletClient.createWalletIntent(), true); finish(); return false; }, false, true); } }); // Click the action button to re-render the screen when the device is unlocked. walletView.setDeviceLockedActionOnClickListener( v -> { Log.d(TAG, "Wallet action button is clicked."); if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { Log.d(TAG, "False tap detected on wallet action button."); return; } mUiEventLogger.log(WalletUiEvent.QAW_UNLOCK_FROM_UNLOCK_BUTTON); mKeyguardDismissUtil.executeWhenUnlocked(() -> false, false, false); }); } @Override protected void onStart() { super.onStart(); if (!mHasRegisteredListener) { // Listener is registered even when device is locked. Should only be registered once. mWalletClient.addWalletServiceEventListener(this); mHasRegisteredListener = true; } mKeyguardStateController.addCallback(mWalletScreenController); mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback); } @Override protected void onResume() { super.onResume(); mWalletScreenController.queryWalletCards(); mKeyguardViewManager.requestFp( true, Utils.getColorAttrDefaultColor( this, com.android.internal.R.attr.colorAccentPrimary)); mKeyguardViewManager.requestFace(true); } @Override protected void onPause() { super.onPause(); mKeyguardViewManager.requestFp(false, -1); mKeyguardViewManager.requestFace(false); } @Override protected void onStop() { super.onStop(); finish(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.wallet_activity_options_menu, menu); return super.onCreateOptionsMenu(menu); } /** * Implements {@link QuickAccessWalletClient.WalletServiceEventListener}. Called when the wallet * application propagates an event, such as an NFC tap, to the quick access wallet view. */ @Override public void onWalletServiceEvent(WalletServiceEvent event) { switch (event.getEventType()) { case WalletServiceEvent.TYPE_NFC_PAYMENT_STARTED: break; case WalletServiceEvent.TYPE_WALLET_CARDS_UPDATED: mWalletScreenController.queryWalletCards(); break; default: Log.w(TAG, "onWalletServiceEvent: Unknown event type"); } } @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { int itemId = item.getItemId(); if (itemId == android.R.id.home) { finish(); return true; } else if (itemId == R.id.wallet_lockscreen_settings) { Intent intent = new Intent(ACTION_LOCKSCREEN_SETTINGS) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); mActivityStarter.startActivity(intent, true); return true; } return super.onOptionsItemSelected(item); } @Override protected void onDestroy() { mKeyguardStateController.removeCallback(mWalletScreenController); if (mKeyguardUpdateMonitorCallback != null) { mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback); } mWalletScreenController.onDismissed(); mWalletClient.removeWalletServiceEventListener(this); mHasRegisteredListener = false; super.onDestroy(); } private Drawable getHomeIndicatorDrawable() { Drawable drawable = getDrawable(R.drawable.ic_close); drawable.setTint(getColor(R.color.material_dynamic_neutral70)); return drawable; } }