diff options
| author | 2021-04-06 23:57:03 -0700 | |
|---|---|---|
| committer | 2021-04-07 15:00:12 +0000 | |
| commit | 01db1e3c64ed51a7131f28071ea07e1c01563651 (patch) | |
| tree | 7d01e73d163dd4559eff405a3313b9afea0115e9 | |
| parent | 245ce41e59d343414a71d05f866e8d218b4d48dd (diff) | |
Launch WalletActivity on Wallet Tile clicked.
If it has cards, open the WalletActivity; otherwise open the wallet app
(e.g. Google Pay).
The WalletActivity can monitor the KeyguardState- if it's locked, prompt
the user to unlock to use the wallet, and once it's unlocked, reload the
"ready to use" UI.
Also a few UI tweaks on the Wallet card carousel screen.
Test: manually test on device, see demo video
https://drive.google.com/file/d/1BzHnEnb0rWGZ1r9_go4pYgzE9A9aStDr/view?usp=sharing&resourcekey=0-Zp1277CmmrlpRGS06d395w
Test: atest
Bug: b/184490333
Bug: b/184306042
Change-Id: Ifcfb8c35ffaff3d5fcda0448f9999965c0a9159c
7 files changed, 116 insertions, 23 deletions
diff --git a/packages/SystemUI/res/drawable/circle_wallet_primary_50dp.xml b/packages/SystemUI/res/drawable/circle_wallet_primary_50dp.xml index de4d882daf53..41d88b4c4ca8 100644 --- a/packages/SystemUI/res/drawable/circle_wallet_primary_50dp.xml +++ b/packages/SystemUI/res/drawable/circle_wallet_primary_50dp.xml @@ -18,5 +18,6 @@ <size android:height="50dp" android:width="50dp" /> - <solid android:color="#1A73E8" /> + <solid android:color="@android:color/transparent" /> + <stroke android:width="2dp" android:color="#AECBFA" /> </shape> 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 bf9655837b25..47212d250c37 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java @@ -48,6 +48,7 @@ import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.settings.SecureSettings; +import com.android.systemui.wallet.ui.WalletActivity; import java.util.List; import java.util.concurrent.Executor; @@ -117,8 +118,22 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> { @Override protected void handleClick() { - mActivityStarter.postStartActivityDismissingKeyguard( - mQuickAccessWalletClient.createWalletIntent(), /* delay= */ 0); + mUiHandler.post(() -> { + mHost.collapsePanels(); + if (mHasCard) { + Intent intent = new Intent(mContext, WalletActivity.class) + .setAction(Intent.ACTION_VIEW) + .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + } else { + if (mQuickAccessWalletClient.createWalletIntent() == null) { + Log.w(TAG, "Could not get intent of the wallet app."); + return; + } + mActivityStarter.postStartActivityDismissingKeyguard( + mQuickAccessWalletClient.createWalletIntent(), /* delay= */ 0); + } + }); } @Override @@ -147,9 +162,7 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> { } else { state.state = Tile.STATE_UNAVAILABLE; } - if (!isDeviceLocked) { - state.sideViewDrawable = mCardViewDrawable; - } + state.sideViewDrawable = isDeviceLocked ? null : mCardViewDrawable; } @Override 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 ba063a8ba303..c1835db9ab0c 100644 --- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java +++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java @@ -28,8 +28,10 @@ import androidx.annotation.NonNull; import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.settings.UserTracker; +import com.android.systemui.statusbar.phone.KeyguardDismissUtil; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.LifecycleActivity; @@ -44,6 +46,7 @@ public class WalletActivity extends LifecycleActivity { private final QuickAccessWalletClient mQuickAccessWalletClient; private final KeyguardStateController mKeyguardStateController; + private final KeyguardDismissUtil mKeyguardDismissUtil; private final ActivityStarter mActivityStarter; private final Executor mExecutor; private final Handler mHandler; @@ -54,12 +57,14 @@ public class WalletActivity extends LifecycleActivity { public WalletActivity( QuickAccessWalletClient quickAccessWalletClient, KeyguardStateController keyguardStateController, + KeyguardDismissUtil keyguardDismissUtil, ActivityStarter activityStarter, @Background Executor executor, - @Background Handler handler, + @Main Handler handler, UserTracker userTracker) { mQuickAccessWalletClient = quickAccessWalletClient; mKeyguardStateController = keyguardStateController; + mKeyguardDismissUtil = keyguardDismissUtil; mActivityStarter = activityStarter; mExecutor = executor; mHandler = handler; @@ -88,20 +93,30 @@ public class WalletActivity extends LifecycleActivity { mExecutor, mHandler, mUserTracker, - !mKeyguardStateController.isUnlocked()); + mKeyguardStateController); + // Clicking the wallet button will open the wallet app if the device is unlocked; bring up + // the security bouncer otherwise. walletView.getWalletButton().setOnClickListener( - v -> mActivityStarter.startActivity( - mQuickAccessWalletClient.createWalletIntent(), true)); + v -> { + if (mKeyguardStateController.isUnlocked()) { + mActivityStarter.startActivity( + mQuickAccessWalletClient.createWalletIntent(), true); + } else { + mKeyguardDismissUtil.executeWhenUnlocked(() -> false, false); + } + }); } @Override protected void onStart() { super.onStart(); + mKeyguardStateController.addCallback(mWalletScreenController); } @Override protected void onResume() { super.onResume(); + mWalletScreenController.queryWalletCards(); } @Override @@ -116,6 +131,7 @@ public class WalletActivity extends LifecycleActivity { @Override protected void onDestroy() { + mKeyguardStateController.removeCallback(mWalletScreenController); mWalletScreenController.onDismissed(); super.onDestroy(); } diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java index a93f0f0ba165..d19506212d91 100644 --- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java +++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java @@ -42,6 +42,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.R; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.settings.UserTracker; +import com.android.systemui.statusbar.policy.KeyguardStateController; import java.util.ArrayList; import java.util.List; @@ -52,7 +53,8 @@ import java.util.concurrent.TimeUnit; public class WalletScreenController implements WalletCardCarousel.OnSelectionListener, QuickAccessWalletClient.OnWalletCardsRetrievedCallback, - QuickAccessWalletClient.WalletServiceEventListener { + QuickAccessWalletClient.WalletServiceEventListener, + KeyguardStateController.Callback { private static final String TAG = "WalletScreenCtrl"; private static final String PREFS_HAS_CARDS = "has_cards"; @@ -65,6 +67,7 @@ public class WalletScreenController implements private final ActivityStarter mActivityStarter; private final Executor mExecutor; private final Handler mHandler; + private final KeyguardStateController mKeyguardStateController; private final Runnable mSelectionRunnable = this::selectCard; private final SharedPreferences mPrefs; private final WalletView mWalletView; @@ -72,7 +75,6 @@ public class WalletScreenController implements @VisibleForTesting String mSelectedCardId; @VisibleForTesting boolean mIsDismissed; - private boolean mIsDeviceLocked; private boolean mHasRegisteredListener; public WalletScreenController( @@ -83,12 +85,13 @@ public class WalletScreenController implements Executor executor, Handler handler, UserTracker userTracker, - boolean isDeviceLocked) { + KeyguardStateController keyguardStateController) { mContext = context; mWalletClient = walletClient; mActivityStarter = activityStarter; mExecutor = executor; mHandler = handler; + mKeyguardStateController = keyguardStateController; mPrefs = userTracker.getUserContext().getSharedPreferences(TAG, Context.MODE_PRIVATE); mWalletView = walletView; mWalletView.setMinimumHeight(getExpectedMinHeight()); @@ -105,7 +108,6 @@ public class WalletScreenController implements // to decrease perceived latency. showEmptyStateView(); } - mIsDeviceLocked = isDeviceLocked; } /** @@ -122,11 +124,17 @@ public class WalletScreenController implements for (WalletCard card : walletCards) { data.add(new QAWalletCardViewInfo(mContext, card)); } + + // Get on main thread for UI updates. mHandler.post(() -> { + if (mIsDismissed) { + return; + } if (data.isEmpty()) { showEmptyStateView(); } else { - mWalletView.showCardCarousel(data, response.getSelectedIndex(), mIsDeviceLocked); + mWalletView.showCardCarousel( + data, response.getSelectedIndex(), !mKeyguardStateController.isUnlocked()); } // The empty state view will not be shown preemptively next time if cards were returned mPrefs.edit().putBoolean(PREFS_HAS_CARDS, !data.isEmpty()).apply(); @@ -140,10 +148,10 @@ public class WalletScreenController implements */ @Override public void onWalletCardRetrievalError(@NonNull GetWalletCardsError error) { - if (mIsDismissed) { - return; - } mHandler.post(() -> { + if (mIsDismissed) { + return; + } mWalletView.showErrorMessage(error.getMessage()); }); } @@ -170,6 +178,11 @@ public class WalletScreenController implements } @Override + public void onKeyguardFadingAwayChanged() { + queryWalletCards(); + } + + @Override public void onCardSelected(@NonNull WalletCardViewInfo card) { if (mIsDismissed) { return; diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java index d2f0720fa66b..a3793945aedf 100644 --- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java +++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java @@ -103,7 +103,9 @@ public class WalletView extends FrameLayout implements WalletCardCarousel.OnCard CharSequence centerCardText = centerCard.getLabel(); Drawable icon = centerCard.getIcon(); if (icon != null) { - mIcon.setImageDrawable(resizeDrawable(getResources(), icon)); + Drawable drawable = resizeDrawable(getResources(), icon); + drawable.setTint(mContext.getColor(R.color.GM2_blue_600)); + mIcon.setImageDrawable(drawable); mIcon.setVisibility(VISIBLE); } else { mIcon.setVisibility(INVISIBLE); @@ -126,7 +128,6 @@ public class WalletView extends FrameLayout implements WalletCardCarousel.OnCard mCardCarouselContainer.setVisibility(VISIBLE); mErrorView.setVisibility(GONE); if (isDeviceLocked) { - // TODO(b/182964813): Add click action to prompt device unlock. mWalletButton.setText(R.string.wallet_button_label_device_locked); } else { mWalletButton.setText(R.string.wallet_button_label_device_unlocked); 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 f57283ff950d..613f879ce80a 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 @@ -30,6 +30,8 @@ import static junit.framework.TestCase.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; @@ -117,10 +119,13 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { @Mock private FeatureFlags mFeatureFlags; @Captor + ArgumentCaptor<Intent> mIntentCaptor; + @Captor ArgumentCaptor<GetWalletCardsRequest> mRequestCaptor; @Captor ArgumentCaptor<QuickAccessWalletClient.OnWalletCardsRetrievedCallback> mCallbackCaptor; + private Context mSpiedContext; private TestableLooper mTestableLooper; private QuickAccessWalletTile mTile; @@ -129,8 +134,10 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mTestableLooper = TestableLooper.get(this); + mSpiedContext = spy(mContext); - when(mHost.getContext()).thenReturn(mContext); + doNothing().when(mSpiedContext).startActivity(any(Intent.class)); + when(mHost.getContext()).thenReturn(mSpiedContext); when(mHost.getUiEventLogger()).thenReturn(mUiEventLogger); when(mFeatureFlags.isQuickAccessWalletEnabled()).thenReturn(true); when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true); @@ -179,16 +186,46 @@ public class QuickAccessWalletTileTest extends SysuiTestCase { } @Test - public void testHandleClick_openGPay() { + public void testHandleClick_noCards_hasIntent_openWalletApp() { Intent intent = new Intent("WalletIntent"); when(mQuickAccessWalletClient.createWalletIntent()).thenReturn(intent); + setUpWalletCard(/* hasCard= */ false); + mTile.handleClick(); + mTestableLooper.processAllMessages(); verify(mActivityStarter, times(1)) .postStartActivityDismissingKeyguard(eq(intent), anyInt()); } @Test + public void testHandleClick_noCards_noIntent_doNothing() { + when(mQuickAccessWalletClient.createWalletIntent()).thenReturn(null); + setUpWalletCard(/* hasCard= */ false); + + mTile.handleClick(); + mTestableLooper.processAllMessages(); + + verifyZeroInteractions(mActivityStarter); + } + + @Test + public void testHandleClick_hasCards_startWalletActivity() { + setUpWalletCard(/* hasCard= */ true); + + mTile.handleClick(); + mTestableLooper.processAllMessages(); + + verify(mSpiedContext).startActivity(mIntentCaptor.capture()); + + Intent nextStartedIntent = mIntentCaptor.getValue(); + String walletClassName = "com.android.systemui.wallet.ui.WalletActivity"; + + assertNotNull(nextStartedIntent); + assertThat(nextStartedIntent.getComponent().getClassName()).isEqualTo(walletClassName); + } + + @Test public void testHandleUpdateState_updateLabelAndIcon() { QSTile.State state = new QSTile.State(); QSTile.Icon icon = QSTileImpl.ResourceIcon.get(R.drawable.ic_qs_wallet); diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java index f85962b6859b..653946ea5cc8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java @@ -51,6 +51,7 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.settings.UserTracker; +import com.android.systemui.statusbar.policy.KeyguardStateController; import com.google.common.util.concurrent.MoreExecutors; @@ -85,6 +86,8 @@ public class WalletScreenControllerTest extends SysuiTestCase { ActivityStarter mActivityStarter; @Mock UserTracker mUserTracker; + @Mock + KeyguardStateController mKeyguardStateController; @Captor ArgumentCaptor<Intent> mIntentCaptor; @Captor @@ -106,6 +109,7 @@ public class WalletScreenControllerTest extends SysuiTestCase { when(mWalletClient.getShortcutShortLabel()).thenReturn(SHORTCUT_SHORT_LABEL); when(mWalletClient.getServiceLabel()).thenReturn(SERVICE_LABEL); when(mWalletClient.createWalletIntent()).thenReturn(mWalletIntent); + when(mKeyguardStateController.isUnlocked()).thenReturn(true); mController = new WalletScreenController( mContext, mWalletView, @@ -114,7 +118,7 @@ public class WalletScreenControllerTest extends SysuiTestCase { MoreExecutors.directExecutor(), new Handler(mTestableLooper.getLooper()), mUserTracker, - /* isDeviceLocked= */false); + mKeyguardStateController); } @Test @@ -206,6 +210,14 @@ public class WalletScreenControllerTest extends SysuiTestCase { } @Test + public void onKeyguardFadingAwayChanged_queryCards() { + mController.onKeyguardFadingAwayChanged(); + + verify(mWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture()); + assertEquals(mController, mCallbackCaptor.getValue()); + } + + @Test public void onCardSelected() { mController.onCardSelected(createCardViewInfo()); |