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()),