Recreate QuickAccessWallet for Wallet Tile and Lockscreen Icon when the default payment app has changed.
Also to avoid a wallet client that doesn't have ServiceInfo is living
too long, don't make it final and re-create the wallet client if it has a null service info.
Fix: 187972400
Test: manual, see demo- the default payment app is GPay, check Tile and
Lockscreen Icon, then change the default payment app and check again.
https://drive.google.com/file/d/10-I339VPuxJRGXJT-XmwmnZs4MHaH3gm/view?usp=sharing&resourcekey=0-wDtRXNNr_Tg9ptxk1Tpxsw
Change-Id: Ie9a05795bff447424b299132fa60ae2efb2092be
(cherry picked from commit bda8ed85a711776dae6ecdd3dfa647b0f9aea9ae)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
index e4679255..611f0e3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -20,9 +20,11 @@
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.database.ContentObserver;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
+import android.provider.Settings;
import android.service.quickaccesswallet.GetWalletCardsError;
import android.service.quickaccesswallet.GetWalletCardsRequest;
import android.service.quickaccesswallet.GetWalletCardsResponse;
@@ -66,16 +68,16 @@
private final CharSequence mLabel = mContext.getString(R.string.wallet_title);
private final WalletCardRetriever mCardRetriever = new WalletCardRetriever();
- // TODO(b/180959290): Re-create the QAW Client when the default NFC payment app changes.
- private final QuickAccessWalletClient mQuickAccessWalletClient;
private final KeyguardStateController mKeyguardStateController;
private final PackageManager mPackageManager;
private final SecureSettings mSecureSettings;
private final Executor mExecutor;
private final FeatureFlags mFeatureFlags;
- @VisibleForTesting Drawable mCardViewDrawable;
+ private QuickAccessWalletClient mQuickAccessWalletClient;
+ private ContentObserver mDefaultPaymentAppObserver;
private WalletCard mSelectedCard;
+ @VisibleForTesting Drawable mCardViewDrawable;
@Inject
public QuickAccessWalletTile(
@@ -87,15 +89,14 @@
StatusBarStateController statusBarStateController,
ActivityStarter activityStarter,
QSLogger qsLogger,
- QuickAccessWalletClient quickAccessWalletClient,
KeyguardStateController keyguardStateController,
PackageManager packageManager,
SecureSettings secureSettings,
- @Background Executor executor,
+ @Main Executor executor,
FeatureFlags featureFlags) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
- mQuickAccessWalletClient = quickAccessWalletClient;
+ mQuickAccessWalletClient = QuickAccessWalletClient.create(mContext);
mKeyguardStateController = keyguardStateController;
mPackageManager = packageManager;
mSecureSettings = secureSettings;
@@ -115,6 +116,12 @@
protected void handleSetListening(boolean listening) {
super.handleSetListening(listening);
if (listening) {
+ setupDefaultPaymentAppObserver();
+ // Re-create wallet client to avoid a client that doesn't have service info is living
+ // too long.
+ if (!mQuickAccessWalletClient.isWalletServiceAvailable()) {
+ reCreateWalletClient();
+ }
queryWalletCards();
}
}
@@ -174,6 +181,7 @@
state.stateDescription = state.secondaryLabel;
} else {
state.state = Tile.STATE_UNAVAILABLE;
+ state.secondaryLabel = null;
}
state.sideViewCustomDrawable = isDeviceLocked ? null : mCardViewDrawable;
}
@@ -202,7 +210,30 @@
return label == null ? mLabel : label;
}
+ @Override
+ protected void handleDestroy() {
+ super.handleDestroy();
+ if (mDefaultPaymentAppObserver != null) {
+ mSecureSettings.unregisterContentObserver(mDefaultPaymentAppObserver);
+ }
+ mQuickAccessWalletClient = null;
+ }
+
+ @VisibleForTesting
+ void overrideQuickAccessWalletClientForTest(QuickAccessWalletClient quickAccessWalletClient) {
+ mQuickAccessWalletClient = quickAccessWalletClient;
+ }
+
+ @VisibleForTesting
+ QuickAccessWalletClient getQuickAccessWalletClient() {
+ return mQuickAccessWalletClient;
+ }
+
private void queryWalletCards() {
+ if (!mQuickAccessWalletClient.isWalletFeatureAvailable()) {
+ Log.w(TAG, "QAW feature not unavailable, unable to query wallet cards,");
+ return;
+ }
int cardWidth =
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_width);
int cardHeight =
@@ -213,6 +244,29 @@
mQuickAccessWalletClient.getWalletCards(mExecutor, request, mCardRetriever);
}
+ private void reCreateWalletClient() {
+ mQuickAccessWalletClient = QuickAccessWalletClient.create(mContext);
+ }
+
+ private void setupDefaultPaymentAppObserver() {
+ if (mDefaultPaymentAppObserver == null) {
+ mDefaultPaymentAppObserver = new ContentObserver(null /* handler */) {
+ @Override
+ public void onChange(boolean selfChange) {
+ mExecutor.execute(() -> {
+ reCreateWalletClient();
+ queryWalletCards();
+ });
+ }
+ };
+
+ mSecureSettings.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT),
+ false /* notifyForDescendants */,
+ mDefaultPaymentAppObserver);
+ }
+ }
+
private class WalletCardRetriever implements
QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 7f919b5..04be581 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -194,6 +194,7 @@
private ActivityIntentHelper mActivityIntentHelper;
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private ContentObserver mWalletPreferenceObserver;
+ private ContentObserver mDefaultPaymentAppObserver;
private SecureSettings mSecureSettings;
public KeyguardBottomAreaView(Context context) {
@@ -335,6 +336,9 @@
if (mWalletPreferenceObserver != null) {
mSecureSettings.unregisterContentObserver(mWalletPreferenceObserver);
}
+ if (mDefaultPaymentAppObserver != null) {
+ mSecureSettings.unregisterContentObserver(mDefaultPaymentAppObserver);
+ }
}
private void initAccessibility() {
@@ -935,9 +939,8 @@
/**
* Initialize the wallet feature, only enabling if the feature is enabled within the platform.
*/
- public void initWallet(QuickAccessWalletClient client, Executor uiExecutor,
- SecureSettings secureSettings) {
- mQuickAccessWalletClient = client;
+ public void initWallet(Executor uiExecutor, SecureSettings secureSettings) {
+ mQuickAccessWalletClient = QuickAccessWalletClient.create(mContext);
mSecureSettings = secureSettings;
setupWalletPreferenceObserver();
updateWalletPreference();
@@ -953,7 +956,9 @@
mWalletPreferenceObserver = new ContentObserver(null /* handler */) {
@Override
public void onChange(boolean selfChange) {
- mUiExecutor.execute(() -> updateWalletPreference());
+ mUiExecutor.execute(() -> {
+ updateWalletPreference();
+ });
}
};
@@ -962,10 +967,30 @@
false /* notifyForDescendants */,
mWalletPreferenceObserver);
}
+
+ if (mDefaultPaymentAppObserver == null) {
+ mDefaultPaymentAppObserver = new ContentObserver(null /* handler */) {
+ @Override
+ public void onChange(boolean selfChange) {
+ mUiExecutor.execute(() -> {
+ mQuickAccessWalletClient = QuickAccessWalletClient.create(mContext);
+ updateWalletPreference();
+ queryWalletCards();
+ updateWalletVisibility();
+ });
+ }
+ };
+
+ mSecureSettings.registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT),
+ false /* notifyForDescendants */,
+ mDefaultPaymentAppObserver);
+ }
}
private void updateWalletPreference() {
- mWalletEnabled = mQuickAccessWalletClient.isWalletFeatureAvailable()
+ mWalletEnabled = mQuickAccessWalletClient.isWalletServiceAvailable()
+ && mQuickAccessWalletClient.isWalletFeatureAvailable()
&& mQuickAccessWalletClient.isWalletFeatureAvailableWhenDeviceLocked();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 9d8a9bf..0e0e145 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -54,7 +54,6 @@
import android.os.SystemClock;
import android.os.UserManager;
import android.os.VibrationEffect;
-import android.service.quickaccesswallet.QuickAccessWalletClient;
import android.util.Log;
import android.util.MathUtils;
import android.view.DisplayCutout;
@@ -573,7 +572,6 @@
private int mScreenCornerRadius;
private int mNotificationScrimPadding;
- private final QuickAccessWalletClient mQuickAccessWalletClient;
private final Executor mUiExecutor;
private final SecureSettings mSecureSettings;
@@ -649,7 +647,6 @@
AmbientState ambientState,
LockIconViewController lockIconViewController,
FeatureFlags featureFlags,
- QuickAccessWalletClient quickAccessWalletClient,
KeyguardMediaController keyguardMediaController,
PrivacyDotViewController privacyDotViewController,
@Main Executor uiExecutor,
@@ -703,7 +700,6 @@
mScrimController.setClipsQsScrim(!mShouldUseSplitNotificationShade);
mUserManager = userManager;
mMediaDataManager = mediaDataManager;
- mQuickAccessWalletClient = quickAccessWalletClient;
mUiExecutor = uiExecutor;
mSecureSettings = secureSettings;
pulseExpansionHandler.setPulseExpandAbortListener(() -> {
@@ -1098,7 +1094,7 @@
mKeyguardBottomArea.setFalsingManager(mFalsingManager);
if (mFeatureFlags.isQuickAccessWalletEnabled()) {
- mKeyguardBottomArea.initWallet(mQuickAccessWalletClient, mUiExecutor, mSecureSettings);
+ mKeyguardBottomArea.initWallet(mUiExecutor, mSecureSettings);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
index 83aa01f..c6123e7 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java
@@ -24,6 +24,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.service.quickaccesswallet.QuickAccessWalletClient;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
@@ -52,7 +53,7 @@
*/
public class WalletActivity extends LifecycleActivity {
- private final QuickAccessWalletClient mQuickAccessWalletClient;
+ private static final String TAG = "WalletActivity";
private final KeyguardStateController mKeyguardStateController;
private final KeyguardDismissUtil mKeyguardDismissUtil;
private final ActivityStarter mActivityStarter;
@@ -65,7 +66,6 @@
@Inject
public WalletActivity(
- QuickAccessWalletClient quickAccessWalletClient,
KeyguardStateController keyguardStateController,
KeyguardDismissUtil keyguardDismissUtil,
ActivityStarter activityStarter,
@@ -74,7 +74,6 @@
FalsingManager falsingManager,
UserTracker userTracker,
StatusBarKeyguardViewManager keyguardViewManager) {
- mQuickAccessWalletClient = quickAccessWalletClient;
mKeyguardStateController = keyguardStateController;
mKeyguardDismissUtil = keyguardDismissUtil;
mActivityStarter = activityStarter;
@@ -103,10 +102,11 @@
getActionBar().setHomeActionContentDescription(R.string.accessibility_desc_close);
WalletView walletView = requireViewById(R.id.wallet_view);
+ QuickAccessWalletClient walletClient = QuickAccessWalletClient.create(this);
mWalletScreenController = new WalletScreenController(
this,
walletView,
- mQuickAccessWalletClient,
+ walletClient,
mActivityStarter,
mExecutor,
mHandler,
@@ -116,6 +116,10 @@
walletView.getAppButton().setOnClickListener(
v -> {
+ if (walletClient.createWalletIntent() == null) {
+ Log.w(TAG, "Unable to create wallet app intent.");
+ return;
+ }
if (!mKeyguardStateController.isUnlocked()
&& mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
return;
@@ -123,12 +127,12 @@
if (mKeyguardStateController.isUnlocked()) {
mActivityStarter.startActivity(
- mQuickAccessWalletClient.createWalletIntent(), true);
+ walletClient.createWalletIntent(), true);
finish();
} else {
mKeyguardDismissUtil.executeWhenUnlocked(() -> {
mActivityStarter.startActivity(
- mQuickAccessWalletClient.createWalletIntent(), true);
+ walletClient.createWalletIntent(), true);
finish();
return false;
}, false, true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index 7533cf1..fdd880d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -21,6 +21,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static junit.framework.Assert.assertNotSame;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertNotNull;
@@ -155,12 +156,12 @@
mStatusBarStateController,
mActivityStarter,
mQSLogger,
- mQuickAccessWalletClient,
mKeyguardStateController,
mPackageManager,
mSecureSettings,
MoreExecutors.directExecutor(),
mFeatureFlags);
+ mTile.overrideQuickAccessWalletClientForTest(mQuickAccessWalletClient);
}
@Test
@@ -175,6 +176,15 @@
}
@Test
+ public void testWalletServiceUnavailable_recreateWalletClient() {
+ when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(false);
+
+ mTile.handleSetListening(true);
+
+ assertNotSame(mQuickAccessWalletClient, mTile.getQuickAccessWalletClient());
+ }
+
+ @Test
public void testIsAvailable_qawFeatureAvailable() {
when(mPackageManager.hasSystemFeature(FEATURE_NFC_HOST_CARD_EMULATION)).thenReturn(true);
when(mPackageManager.hasSystemFeature("org.chromium.arc")).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 6b4797f..4fc3bfe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -39,7 +39,6 @@
import android.hardware.biometrics.BiometricSourceType;
import android.os.PowerManager;
import android.os.UserManager;
-import android.service.quickaccesswallet.QuickAccessWalletClient;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.DisplayMetrics;
@@ -245,8 +244,6 @@
@Mock
private LockIconViewController mLockIconViewController;
@Mock
- private QuickAccessWalletClient mQuickAccessWalletClient;
- @Mock
private KeyguardMediaController mKeyguardMediaController;
@Mock
private PrivacyDotViewController mPrivacyDotViewController;
@@ -361,7 +358,6 @@
mAmbientState,
mLockIconViewController,
mFeatureFlags,
- mQuickAccessWalletClient,
mKeyguardMediaController,
mPrivacyDotViewController,
new FakeExecutor(new FakeSystemClock()),