summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Silin Huang <silin@google.com> 2021-04-06 23:57:03 -0700
committer Silin Huang <silin@google.com> 2021-04-07 15:00:12 +0000
commit01db1e3c64ed51a7131f28071ea07e1c01563651 (patch)
tree7d01e73d163dd4559eff405a3313b9afea0115e9
parent245ce41e59d343414a71d05f866e8d218b4d48dd (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
-rw-r--r--packages/SystemUI/res/drawable/circle_wallet_primary_50dp.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java41
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java14
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());