Update wallet tile secondary label when QAW cards fetching in flight.

Also re-create the QAW client if the wallet feature is unavailable; and query the wallet cards only when the wallet feature is available.

Test: atest
Test: manual
Bug: 190036483
Change-Id: Ibad3429a6f77d3f8a474b577759e7b7193ad6f23
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index bc1c67c..e705803 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1661,6 +1661,8 @@
     <string name="wallet_action_button_label_unlock">Unlock to pay</string>
     <!-- Secondary label of the quick access wallet tile if no card. [CHAR LIMIT=NONE] -->
     <string name="wallet_secondary_label_no_card">Not set up</string>
+    <!-- Secondary label of the quick access wallet tile if wallet is still updating. [CHAR LIMIT=NONE] -->
+    <string name="wallet_secondary_label_updating">Updating</string>
     <!-- Secondary label of the quick access wallet tile if device locked. [CHAR LIMIT=NONE] -->
     <string name="wallet_secondary_label_device_locked">Unlock to use</string>
     <!-- Message shown when an unknown failure occurred when fetching cards. [CHAR LIMIT=NONE] -->
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 98cd88a..4dc7508 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -73,6 +73,7 @@
     private final QuickAccessWalletController mController;
 
     private WalletCard mSelectedCard;
+    private boolean mIsWalletUpdating = true;
     @VisibleForTesting Drawable mCardViewDrawable;
 
     @Inject
@@ -110,7 +111,8 @@
         super.handleSetListening(listening);
         if (listening) {
             mController.setupWalletChangeObservers(mCardRetriever, DEFAULT_PAYMENT_APP_CHANGE);
-            if (!mController.getWalletClient().isWalletServiceAvailable()) {
+            if (!mController.getWalletClient().isWalletServiceAvailable()
+                    || !mController.getWalletClient().isWalletFeatureAvailable()) {
                 Log.i(TAG, "QAW service is unavailable, recreating the wallet client.");
                 mController.reCreateWalletClient();
             }
@@ -158,7 +160,8 @@
         state.contentDescription = state.label;
         state.icon = ResourceIcon.get(R.drawable.ic_wallet_lockscreen);
         boolean isDeviceLocked = !mKeyguardStateController.isUnlocked();
-        if (mController.getWalletClient().isWalletServiceAvailable()) {
+        if (mController.getWalletClient().isWalletServiceAvailable()
+                && mController.getWalletClient().isWalletFeatureAvailable()) {
             if (mSelectedCard != null) {
                 if (isDeviceLocked) {
                     state.state = Tile.STATE_INACTIVE;
@@ -172,7 +175,11 @@
                 }
             } else {
                 state.state = Tile.STATE_INACTIVE;
-                state.secondaryLabel = mContext.getString(R.string.wallet_secondary_label_no_card);
+                state.secondaryLabel =
+                        mContext.getString(
+                                mIsWalletUpdating
+                                        ? R.string.wallet_secondary_label_updating
+                                        : R.string.wallet_secondary_label_no_card);
                 state.sideViewCustomDrawable = null;
             }
             state.stateDescription = state.secondaryLabel;
@@ -218,6 +225,7 @@
         @Override
         public void onWalletCardsRetrieved(@NonNull GetWalletCardsResponse response) {
             Log.i(TAG, "Successfully retrieved wallet cards.");
+            mIsWalletUpdating = false;
             List<WalletCard> cards = response.getWalletCards();
             if (cards.isEmpty()) {
                 Log.d(TAG, "No wallet cards exist.");
@@ -240,7 +248,7 @@
 
         @Override
         public void onWalletCardRetrievalError(@NonNull GetWalletCardsError error) {
-            Log.w(TAG, "Error retrieve wallet cards");
+            mIsWalletUpdating = false;
             mCardViewDrawable = null;
             mSelectedCard = null;
             refreshState();
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
index 65f236b..a262bf1 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
@@ -25,10 +25,11 @@
 import android.service.quickaccesswallet.GetWalletCardsRequest;
 import android.service.quickaccesswallet.QuickAccessWalletClient;
 import android.service.quickaccesswallet.QuickAccessWalletClientImpl;
+import android.util.Log;
 
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.util.settings.SecureSettings;
 
 import java.util.concurrent.Executor;
@@ -65,7 +66,7 @@
     @Inject
     public QuickAccessWalletController(
             Context context,
-            @Main Executor executor,
+            @Background Executor executor,
             SecureSettings secureSettings,
             QuickAccessWalletClient quickAccessWalletClient) {
         mContext = context;
@@ -142,6 +143,10 @@
      */
     public void queryWalletCards(
             QuickAccessWalletClient.OnWalletCardsRetrievedCallback cardsRetriever) {
+        if (!mQuickAccessWalletClient.isWalletFeatureAvailable()) {
+            Log.d(TAG, "QuickAccessWallet feature is not available.");
+            return;
+        }
         int cardWidth =
                 mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_width);
         int cardHeight =
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 a50cbe5..b1e67f5 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
@@ -175,6 +175,15 @@
     }
 
     @Test
+    public void testWalletFeatureUnavailable_recreateWalletClient() {
+        when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(false);
+
+        mTile.handleSetListening(true);
+
+        verify(mController, times(1)).reCreateWalletClient();
+    }
+
+    @Test
     public void testIsAvailable_qawFeatureAvailable() {
         when(mPackageManager.hasSystemFeature(FEATURE_NFC_HOST_CARD_EMULATION)).thenReturn(true);
         when(mPackageManager.hasSystemFeature("org.chromium.arc")).thenReturn(false);
@@ -267,6 +276,41 @@
     }
 
     @Test
+    public void testHandleUpdateState_walletIsUpdating() {
+        when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+        QSTile.State state = new QSTile.State();
+        GetWalletCardsResponse response =
+                new GetWalletCardsResponse(
+                        Collections.singletonList(createWalletCard(mContext)), 0);
+
+        mTile.handleSetListening(true);
+
+        verify(mController).queryWalletCards(mCallbackCaptor.capture());
+
+        // Wallet cards fetching on its way; wallet updating.
+        mTile.handleUpdateState(state, null);
+
+        assertEquals(Tile.STATE_INACTIVE, state.state);
+        assertEquals(
+                mContext.getString(R.string.wallet_secondary_label_updating), state.secondaryLabel);
+        assertNotNull(state.stateDescription);
+        assertNull(state.sideViewCustomDrawable);
+
+        // Wallet cards fetching completed.
+        mCallbackCaptor.getValue().onWalletCardsRetrieved(response);
+        mTestableLooper.processAllMessages();
+
+        mTile.handleUpdateState(state, null);
+
+        assertEquals(Tile.STATE_ACTIVE, state.state);
+        assertEquals(
+                "•••• 1234",
+                state.secondaryLabel);
+        assertNotNull(state.stateDescription);
+        assertNotNull(state.sideViewCustomDrawable);
+    }
+
+    @Test
     public void testHandleUpdateState_hasCard_deviceLocked_tileInactive() {
         when(mKeyguardStateController.isUnlocked()).thenReturn(false);
         QSTile.State state = new QSTile.State();
@@ -315,7 +359,7 @@
     }
 
     @Test
-    public void testHandleUpdateState_qawFeatureUnavailable_tileUnavailable() {
+    public void testHandleUpdateState_qawServiceUnavailable_tileUnavailable() {
         when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(false);
         QSTile.State state = new QSTile.State();
 
@@ -327,6 +371,18 @@
     }
 
     @Test
+    public void testHandleUpdateState_qawFeatureUnavailable_tileUnavailable() {
+        when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(false);
+        QSTile.State state = new QSTile.State();
+
+        mTile.handleUpdateState(state, null);
+
+        assertEquals(Tile.STATE_UNAVAILABLE, state.state);
+        assertNull(state.stateDescription);
+        assertNull(state.sideViewCustomDrawable);
+    }
+
+    @Test
     public void testHandleSetListening_queryCards() {
         mTile.handleSetListening(true);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java
index 23abce0..ce0098e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java
@@ -21,7 +21,9 @@
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -61,12 +63,10 @@
     private ArgumentCaptor<GetWalletCardsRequest> mRequestCaptor;
 
     private QuickAccessWalletController mController;
-    private TestableLooper mTestableLooper;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mTestableLooper = TestableLooper.get(this);
         when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(true);
         when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true);
         when(mQuickAccessWalletClient.isWalletFeatureAvailableWhenDeviceLocked()).thenReturn(true);
@@ -143,4 +143,13 @@
                 mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_height),
                 request.getCardHeightPx());
     }
+
+    @Test
+    public void queryWalletCards_walletFeatureNotAvailable_noQuery() {
+        when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(false);
+
+        mController.queryWalletCards(mCardsRetriever);
+
+        verify(mQuickAccessWalletClient, never()).getWalletCards(any(), any(), any());
+    }
 }