Merge "Support non-active tokens in QuickAccessWallet." into sc-dev
This commit is contained in:
@@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2019 The Android Open Source Project
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
-->
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:shape="oval">
|
|
||||||
<size
|
|
||||||
android:height="56dp"
|
|
||||||
android:width="56dp" />
|
|
||||||
<solid android:color="@android:color/transparent" />
|
|
||||||
<stroke android:width="2dp" android:color="@color/GM2_grey_300" />
|
|
||||||
</shape>
|
|
||||||
@@ -19,6 +19,13 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clipChildren="false">
|
android:clipChildren="false">
|
||||||
|
<Toolbar
|
||||||
|
android:id="@+id/action_bar"
|
||||||
|
style="?android:attr/actionBarStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:navigationContentDescription="@null" />
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/card_carousel_container"
|
android:id="@+id/card_carousel_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- Copyright (C) 2019 The Android Open Source Project
|
<!--
|
||||||
|
Copyright (C) 2021 The Android Open Source Project
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -13,11 +14,11 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
android:shape="oval">
|
<item
|
||||||
<size
|
android:id="@+id/wallet_lockscreen_settings"
|
||||||
android:height="56dp"
|
android:enabled="true"
|
||||||
android:width="56dp" />
|
android:showAsAction="never"
|
||||||
<solid android:color="@android:color/transparent" />
|
android:title="@string/wallet_lockscreen_settings_label"
|
||||||
<stroke android:width="2dp" android:color="#AECBFA" />
|
android:visible="true" />
|
||||||
</shape>
|
</menu>
|
||||||
@@ -1483,6 +1483,7 @@
|
|||||||
|
|
||||||
<!-- Wallet activity screen specs -->
|
<!-- Wallet activity screen specs -->
|
||||||
<dimen name="wallet_icon_size">36sp</dimen>
|
<dimen name="wallet_icon_size">36sp</dimen>
|
||||||
|
<dimen name="wallet_view_header_icon_size">56dp</dimen>
|
||||||
<dimen name="card_margin">16dp</dimen>
|
<dimen name="card_margin">16dp</dimen>
|
||||||
<dimen name="card_carousel_dot_offset">24dp</dimen>
|
<dimen name="card_carousel_dot_offset">24dp</dimen>
|
||||||
<dimen name="card_carousel_dot_unselected_radius">2dp</dimen>
|
<dimen name="card_carousel_dot_unselected_radius">2dp</dimen>
|
||||||
|
|||||||
@@ -1656,14 +1656,14 @@
|
|||||||
<string name="wallet_app_button_label">Show all</string>
|
<string name="wallet_app_button_label">Show all</string>
|
||||||
<!-- Label of the button underneath the card carousel prompting user unlock device. [CHAR LIMIT=NONE] -->
|
<!-- Label of the button underneath the card carousel prompting user unlock device. [CHAR LIMIT=NONE] -->
|
||||||
<string name="wallet_action_button_label_unlock">Unlock to pay</string>
|
<string name="wallet_action_button_label_unlock">Unlock to pay</string>
|
||||||
<!-- Secondary label of the quick access wallet tile if active. [CHAR LIMIT=32] -->
|
|
||||||
<string name="wallet_secondary_label_active">Ready</string>
|
|
||||||
<!-- Secondary label of the quick access wallet tile if no card. [CHAR LIMIT=NONE] -->
|
<!-- Secondary label of the quick access wallet tile if no card. [CHAR LIMIT=NONE] -->
|
||||||
<string name="wallet_secondary_label_no_card">Set up payment</string>
|
<string name="wallet_secondary_label_no_card">Not set up</string>
|
||||||
<!-- Secondary label of the quick access wallet tile if device locked. [CHAR LIMIT=NONE] -->
|
<!-- 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>
|
<string name="wallet_secondary_label_device_locked">Unlock to use</string>
|
||||||
<!-- Message shown when an unknown failure occurred when fetching cards. [CHAR LIMIT=NONE] -->
|
<!-- Message shown when an unknown failure occurred when fetching cards. [CHAR LIMIT=NONE] -->
|
||||||
<string name="wallet_error_generic">There was a problem getting your cards, please try again later</string>
|
<string name="wallet_error_generic">There was a problem getting your cards, please try again later</string>
|
||||||
|
<!-- Overflow menu item label to open the lockscreen settings in wallet activity. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="wallet_lockscreen_settings_label">Lock screen settings</string>
|
||||||
|
|
||||||
<!-- Name of the work status bar icon. -->
|
<!-- Name of the work status bar icon. -->
|
||||||
<string name="status_bar_work">Work profile</string>
|
<string name="status_bar_work">Work profile</string>
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
|
|||||||
private final FeatureFlags mFeatureFlags;
|
private final FeatureFlags mFeatureFlags;
|
||||||
|
|
||||||
@VisibleForTesting Drawable mCardViewDrawable;
|
@VisibleForTesting Drawable mCardViewDrawable;
|
||||||
private boolean mHasCard;
|
private WalletCard mSelectedCard;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public QuickAccessWalletTile(
|
public QuickAccessWalletTile(
|
||||||
@@ -125,7 +125,7 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
|
|||||||
view == null ? null : ActivityLaunchAnimator.Controller.fromView(view);
|
view == null ? null : ActivityLaunchAnimator.Controller.fromView(view);
|
||||||
|
|
||||||
mUiHandler.post(() -> {
|
mUiHandler.post(() -> {
|
||||||
if (mHasCard) {
|
if (mSelectedCard != null) {
|
||||||
Intent intent = new Intent(mContext, WalletActivity.class)
|
Intent intent = new Intent(mContext, WalletActivity.class)
|
||||||
.setAction(Intent.ACTION_VIEW)
|
.setAction(Intent.ACTION_VIEW)
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
@@ -157,15 +157,14 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
|
|||||||
state.icon = ResourceIcon.get(R.drawable.ic_wallet_lockscreen);
|
state.icon = ResourceIcon.get(R.drawable.ic_wallet_lockscreen);
|
||||||
boolean isDeviceLocked = !mKeyguardStateController.isUnlocked();
|
boolean isDeviceLocked = !mKeyguardStateController.isUnlocked();
|
||||||
if (mQuickAccessWalletClient.isWalletServiceAvailable()) {
|
if (mQuickAccessWalletClient.isWalletServiceAvailable()) {
|
||||||
if (mHasCard) {
|
if (mSelectedCard != null) {
|
||||||
if (isDeviceLocked) {
|
if (isDeviceLocked) {
|
||||||
state.state = Tile.STATE_INACTIVE;
|
state.state = Tile.STATE_INACTIVE;
|
||||||
state.secondaryLabel =
|
state.secondaryLabel =
|
||||||
mContext.getString(R.string.wallet_secondary_label_device_locked);
|
mContext.getString(R.string.wallet_secondary_label_device_locked);
|
||||||
} else {
|
} else {
|
||||||
state.state = Tile.STATE_ACTIVE;
|
state.state = Tile.STATE_ACTIVE;
|
||||||
state.secondaryLabel =
|
state.secondaryLabel = mSelectedCard.getContentDescription();
|
||||||
mContext.getString(R.string.wallet_secondary_label_active);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
state.state = Tile.STATE_INACTIVE;
|
state.state = Tile.STATE_INACTIVE;
|
||||||
@@ -208,7 +207,7 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
|
|||||||
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_height);
|
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_height);
|
||||||
int iconSizePx = mContext.getResources().getDimensionPixelSize(R.dimen.wallet_icon_size);
|
int iconSizePx = mContext.getResources().getDimensionPixelSize(R.dimen.wallet_icon_size);
|
||||||
GetWalletCardsRequest request =
|
GetWalletCardsRequest request =
|
||||||
new GetWalletCardsRequest(cardWidth, cardHeight, iconSizePx, /* maxCards= */ 2);
|
new GetWalletCardsRequest(cardWidth, cardHeight, iconSizePx, /* maxCards= */ 1);
|
||||||
mQuickAccessWalletClient.getWalletCards(mExecutor, request, mCardRetriever);
|
mQuickAccessWalletClient.getWalletCards(mExecutor, request, mCardRetriever);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +221,7 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
|
|||||||
if (cards.isEmpty()) {
|
if (cards.isEmpty()) {
|
||||||
Log.d(TAG, "No wallet cards exist.");
|
Log.d(TAG, "No wallet cards exist.");
|
||||||
mCardViewDrawable = null;
|
mCardViewDrawable = null;
|
||||||
mHasCard = false;
|
mSelectedCard = null;
|
||||||
refreshState();
|
refreshState();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -231,8 +230,8 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
|
|||||||
Log.d(TAG, "Selected card index out of bounds.");
|
Log.d(TAG, "Selected card index out of bounds.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mCardViewDrawable = cards.get(selectedIndex).getCardImage().loadDrawable(mContext);
|
mSelectedCard = cards.get(selectedIndex);
|
||||||
mHasCard = true;
|
mCardViewDrawable = mSelectedCard.getCardImage().loadDrawable(mContext);
|
||||||
refreshState();
|
refreshState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +239,7 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
|
|||||||
public void onWalletCardRetrievalError(@NonNull GetWalletCardsError error) {
|
public void onWalletCardRetrievalError(@NonNull GetWalletCardsError error) {
|
||||||
Log.w(TAG, "Error retrieve wallet cards");
|
Log.w(TAG, "Error retrieve wallet cards");
|
||||||
mCardViewDrawable = null;
|
mCardViewDrawable = null;
|
||||||
mHasCard = false;
|
mSelectedCard = null;
|
||||||
refreshState();
|
refreshState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,14 @@
|
|||||||
|
|
||||||
package com.android.systemui.wallet.ui;
|
package com.android.systemui.wallet.ui;
|
||||||
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.drawable.ColorDrawable;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.service.quickaccesswallet.QuickAccessWalletClient;
|
import android.service.quickaccesswallet.QuickAccessWalletClient;
|
||||||
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.Toolbar;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ import com.android.systemui.R;
|
|||||||
import com.android.systemui.dagger.qualifiers.Background;
|
import com.android.systemui.dagger.qualifiers.Background;
|
||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
|
import com.android.systemui.plugins.FalsingManager;
|
||||||
import com.android.systemui.settings.UserTracker;
|
import com.android.systemui.settings.UserTracker;
|
||||||
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
|
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
@@ -50,6 +52,7 @@ public class WalletActivity extends LifecycleActivity {
|
|||||||
private final ActivityStarter mActivityStarter;
|
private final ActivityStarter mActivityStarter;
|
||||||
private final Executor mExecutor;
|
private final Executor mExecutor;
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
|
private final FalsingManager mFalsingManager;
|
||||||
private final UserTracker mUserTracker;
|
private final UserTracker mUserTracker;
|
||||||
private WalletScreenController mWalletScreenController;
|
private WalletScreenController mWalletScreenController;
|
||||||
|
|
||||||
@@ -61,6 +64,7 @@ public class WalletActivity extends LifecycleActivity {
|
|||||||
ActivityStarter activityStarter,
|
ActivityStarter activityStarter,
|
||||||
@Background Executor executor,
|
@Background Executor executor,
|
||||||
@Main Handler handler,
|
@Main Handler handler,
|
||||||
|
FalsingManager falsingManager,
|
||||||
UserTracker userTracker) {
|
UserTracker userTracker) {
|
||||||
mQuickAccessWalletClient = quickAccessWalletClient;
|
mQuickAccessWalletClient = quickAccessWalletClient;
|
||||||
mKeyguardStateController = keyguardStateController;
|
mKeyguardStateController = keyguardStateController;
|
||||||
@@ -68,19 +72,23 @@ public class WalletActivity extends LifecycleActivity {
|
|||||||
mActivityStarter = activityStarter;
|
mActivityStarter = activityStarter;
|
||||||
mExecutor = executor;
|
mExecutor = executor;
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
|
mFalsingManager = falsingManager;
|
||||||
mUserTracker = userTracker;
|
mUserTracker = userTracker;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||||
|
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||||
setContentView(R.layout.quick_access_wallet);
|
setContentView(R.layout.quick_access_wallet);
|
||||||
|
|
||||||
getWindow().getDecorView().setBackgroundColor(getColor(R.color.wallet_white));
|
Toolbar toolbar = findViewById(R.id.action_bar);
|
||||||
|
if (toolbar != null) {
|
||||||
|
setActionBar(toolbar);
|
||||||
|
}
|
||||||
setTitle("");
|
setTitle("");
|
||||||
getActionBar().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
getActionBar().setHomeAsUpIndicator(R.drawable.ic_close);
|
getActionBar().setHomeAsUpIndicator(R.drawable.ic_close);
|
||||||
getActionBar().setHomeActionContentDescription(R.string.accessibility_desc_close);
|
getActionBar().setHomeActionContentDescription(R.string.accessibility_desc_close);
|
||||||
@@ -93,15 +101,28 @@ public class WalletActivity extends LifecycleActivity {
|
|||||||
mExecutor,
|
mExecutor,
|
||||||
mHandler,
|
mHandler,
|
||||||
mUserTracker,
|
mUserTracker,
|
||||||
|
mFalsingManager,
|
||||||
mKeyguardStateController);
|
mKeyguardStateController);
|
||||||
|
|
||||||
walletView.getAppButton().setOnClickListener(
|
walletView.getAppButton().setOnClickListener(
|
||||||
v -> mActivityStarter.startActivity(
|
v -> {
|
||||||
mQuickAccessWalletClient.createWalletIntent(), true));
|
if (!mKeyguardStateController.isUnlocked()
|
||||||
|
&& mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mActivityStarter.startActivity(
|
||||||
|
mQuickAccessWalletClient.createWalletIntent(), true);
|
||||||
|
finish();
|
||||||
|
});
|
||||||
// Click the action button to re-render the screen when the device is unlocked.
|
// Click the action button to re-render the screen when the device is unlocked.
|
||||||
if (!mKeyguardStateController.isUnlocked()) {
|
if (!mKeyguardStateController.isUnlocked()) {
|
||||||
walletView.getActionButton().setOnClickListener(
|
walletView.getActionButton().setOnClickListener(
|
||||||
v -> mKeyguardDismissUtil.executeWhenUnlocked(() -> false, false));
|
v -> {
|
||||||
|
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mKeyguardDismissUtil.executeWhenUnlocked(() -> false, false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,12 +138,21 @@ public class WalletActivity extends LifecycleActivity {
|
|||||||
mWalletScreenController.queryWalletCards();
|
mWalletScreenController.queryWalletCards();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
getMenuInflater().inflate(R.menu.wallet_activity_options_menu, menu);
|
||||||
|
return super.onCreateOptionsMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||||
int itemId = item.getItemId();
|
int itemId = item.getItemId();
|
||||||
if (itemId == android.R.id.home) {
|
if (itemId == android.R.id.home) {
|
||||||
finish();
|
finish();
|
||||||
return true;
|
return true;
|
||||||
|
} else if (itemId == R.id.wallet_lockscreen_settings) {
|
||||||
|
// TODO(b/186496392): Navigate to Lock Screen Settings page when the item is clicked.
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,8 +205,8 @@ public class WalletCardCarousel extends RecyclerView {
|
|||||||
boolean setData(List<WalletCardViewInfo> data, int selectedIndex) {
|
boolean setData(List<WalletCardViewInfo> data, int selectedIndex) {
|
||||||
boolean wasEmpty = mWalletCardCarouselAdapter.getItemCount() == 0;
|
boolean wasEmpty = mWalletCardCarouselAdapter.getItemCount() == 0;
|
||||||
mWalletCardCarouselAdapter.setData(data);
|
mWalletCardCarouselAdapter.setData(data);
|
||||||
|
scrollToPosition(selectedIndex);
|
||||||
if (wasEmpty) {
|
if (wasEmpty) {
|
||||||
scrollToPosition(selectedIndex);
|
|
||||||
mNumCardsToAnimate = numCardsOnScreen(data.size(), selectedIndex);
|
mNumCardsToAnimate = numCardsOnScreen(data.size(), selectedIndex);
|
||||||
mCardAnimationStartPosition = Math.max(selectedIndex - 1, 0);
|
mCardAnimationStartPosition = Math.max(selectedIndex - 1, 0);
|
||||||
}
|
}
|
||||||
@@ -427,15 +427,6 @@ public class WalletCardCarousel extends RecyclerView {
|
|||||||
mSelectionListener.onCardClicked(cardViewInfo);
|
mSelectionListener.onCardClicked(cardViewInfo);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (mNumCardsToAnimate > 0 && (position - mCardAnimationStartPosition < 2)) {
|
|
||||||
mNumCardsToAnimate--;
|
|
||||||
int startDelay = (position - mCardAnimationStartPosition) * CARD_ANIM_ALPHA_DELAY
|
|
||||||
+ mExtraAnimationDelay;
|
|
||||||
viewHolder.itemView.setAlpha(0f);
|
|
||||||
viewHolder.itemView.animate().alpha(1f)
|
|
||||||
.setStartDelay(Math.max(0, startDelay))
|
|
||||||
.setDuration(CARD_ANIM_ALPHA_DURATION).start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.systemui.wallet.ui;
|
package com.android.systemui.wallet.ui;
|
||||||
|
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -47,4 +48,10 @@ interface WalletCardViewInfo {
|
|||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
CharSequence getLabel();
|
CharSequence getLabel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pending intent upon the card is clicked.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
PendingIntent getPendingIntent();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.systemui.wallet.ui;
|
package com.android.systemui.wallet.ui;
|
||||||
|
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
@@ -41,6 +42,7 @@ import androidx.annotation.NonNull;
|
|||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
|
import com.android.systemui.plugins.FalsingManager;
|
||||||
import com.android.systemui.settings.UserTracker;
|
import com.android.systemui.settings.UserTracker;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
|
|
||||||
@@ -57,7 +59,6 @@ public class WalletScreenController implements
|
|||||||
KeyguardStateController.Callback {
|
KeyguardStateController.Callback {
|
||||||
|
|
||||||
private static final String TAG = "WalletScreenCtrl";
|
private static final String TAG = "WalletScreenCtrl";
|
||||||
private static final String PREFS_HAS_CARDS = "has_cards";
|
|
||||||
private static final String PREFS_WALLET_VIEW_HEIGHT = "wallet_view_height";
|
private static final String PREFS_WALLET_VIEW_HEIGHT = "wallet_view_height";
|
||||||
private static final int MAX_CARDS = 10;
|
private static final int MAX_CARDS = 10;
|
||||||
private static final long SELECTION_DELAY_MILLIS = TimeUnit.SECONDS.toMillis(30);
|
private static final long SELECTION_DELAY_MILLIS = TimeUnit.SECONDS.toMillis(30);
|
||||||
@@ -72,6 +73,7 @@ public class WalletScreenController implements
|
|||||||
private final SharedPreferences mPrefs;
|
private final SharedPreferences mPrefs;
|
||||||
private final WalletView mWalletView;
|
private final WalletView mWalletView;
|
||||||
private final WalletCardCarousel mCardCarousel;
|
private final WalletCardCarousel mCardCarousel;
|
||||||
|
private final FalsingManager mFalsingManager;
|
||||||
|
|
||||||
@VisibleForTesting String mSelectedCardId;
|
@VisibleForTesting String mSelectedCardId;
|
||||||
@VisibleForTesting boolean mIsDismissed;
|
@VisibleForTesting boolean mIsDismissed;
|
||||||
@@ -85,12 +87,14 @@ public class WalletScreenController implements
|
|||||||
Executor executor,
|
Executor executor,
|
||||||
Handler handler,
|
Handler handler,
|
||||||
UserTracker userTracker,
|
UserTracker userTracker,
|
||||||
|
FalsingManager falsingManager,
|
||||||
KeyguardStateController keyguardStateController) {
|
KeyguardStateController keyguardStateController) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mWalletClient = walletClient;
|
mWalletClient = walletClient;
|
||||||
mActivityStarter = activityStarter;
|
mActivityStarter = activityStarter;
|
||||||
mExecutor = executor;
|
mExecutor = executor;
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
|
mFalsingManager = falsingManager;
|
||||||
mKeyguardStateController = keyguardStateController;
|
mKeyguardStateController = keyguardStateController;
|
||||||
mPrefs = userTracker.getUserContext().getSharedPreferences(TAG, Context.MODE_PRIVATE);
|
mPrefs = userTracker.getUserContext().getSharedPreferences(TAG, Context.MODE_PRIVATE);
|
||||||
mWalletView = walletView;
|
mWalletView = walletView;
|
||||||
@@ -102,12 +106,6 @@ public class WalletScreenController implements
|
|||||||
if (mCardCarousel != null) {
|
if (mCardCarousel != null) {
|
||||||
mCardCarousel.setSelectionListener(this);
|
mCardCarousel.setSelectionListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mPrefs.getBoolean(PREFS_HAS_CARDS, false)) {
|
|
||||||
// The empty state view is shown preemptively when cards were not returned last time
|
|
||||||
// to decrease perceived latency.
|
|
||||||
showEmptyStateView();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -136,8 +134,6 @@ public class WalletScreenController implements
|
|||||||
mWalletView.showCardCarousel(
|
mWalletView.showCardCarousel(
|
||||||
data, response.getSelectedIndex(), !mKeyguardStateController.isUnlocked());
|
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();
|
|
||||||
removeMinHeightAndRecordHeightOnLayout();
|
removeMinHeightAndRecordHeightOnLayout();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -167,7 +163,6 @@ public class WalletScreenController implements
|
|||||||
}
|
}
|
||||||
switch (event.getEventType()) {
|
switch (event.getEventType()) {
|
||||||
case WalletServiceEvent.TYPE_NFC_PAYMENT_STARTED:
|
case WalletServiceEvent.TYPE_NFC_PAYMENT_STARTED:
|
||||||
onDismissed();
|
|
||||||
break;
|
break;
|
||||||
case WalletServiceEvent.TYPE_WALLET_CARDS_UPDATED:
|
case WalletServiceEvent.TYPE_WALLET_CARDS_UPDATED:
|
||||||
queryWalletCards();
|
queryWalletCards();
|
||||||
@@ -207,14 +202,17 @@ public class WalletScreenController implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCardClicked(@NonNull WalletCardViewInfo cardInfo) {
|
public void onCardClicked(@NonNull WalletCardViewInfo cardInfo) {
|
||||||
|
if (!mKeyguardStateController.isUnlocked()
|
||||||
|
&& mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!(cardInfo instanceof QAWalletCardViewInfo)
|
if (!(cardInfo instanceof QAWalletCardViewInfo)
|
||||||
|| ((QAWalletCardViewInfo) cardInfo).mWalletCard == null
|
|| ((QAWalletCardViewInfo) cardInfo).mWalletCard == null
|
||||||
|| ((QAWalletCardViewInfo) cardInfo).mWalletCard.getPendingIntent() == null) {
|
|| ((QAWalletCardViewInfo) cardInfo).mWalletCard.getPendingIntent() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mActivityStarter.startActivity(
|
mActivityStarter.startActivity(
|
||||||
((QAWalletCardViewInfo) cardInfo).mWalletCard.getPendingIntent().getIntent(),
|
((QAWalletCardViewInfo) cardInfo).mWalletCard.getPendingIntent().getIntent(), true);
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -235,7 +233,8 @@ public class WalletScreenController implements
|
|||||||
|
|
||||||
mWalletView.show();
|
mWalletView.show();
|
||||||
mWalletView.hideErrorMessage();
|
mWalletView.hideErrorMessage();
|
||||||
int iconSizePx = mContext.getResources().getDimensionPixelSize(R.dimen.wallet_icon_size);
|
int iconSizePx =
|
||||||
|
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_view_header_icon_size);
|
||||||
GetWalletCardsRequest request =
|
GetWalletCardsRequest request =
|
||||||
new GetWalletCardsRequest(cardWidthPx, cardHeightPx, iconSizePx, MAX_CARDS);
|
new GetWalletCardsRequest(cardWidthPx, cardHeightPx, iconSizePx, MAX_CARDS);
|
||||||
mWalletClient.getWalletCards(mExecutor, request, this);
|
mWalletClient.getWalletCards(mExecutor, request, this);
|
||||||
@@ -248,6 +247,7 @@ public class WalletScreenController implements
|
|||||||
mIsDismissed = true;
|
mIsDismissed = true;
|
||||||
mSelectedCardId = null;
|
mSelectedCardId = null;
|
||||||
mHandler.removeCallbacks(mSelectionRunnable);
|
mHandler.removeCallbacks(mSelectionRunnable);
|
||||||
|
mFalsingManager.cleanup();
|
||||||
mWalletClient.notifyWalletDismissed();
|
mWalletClient.notifyWalletDismissed();
|
||||||
mWalletClient.removeWalletServiceEventListener(this);
|
mWalletClient.removeWalletServiceEventListener(this);
|
||||||
mWalletView.animateDismissal();
|
mWalletView.animateDismissal();
|
||||||
@@ -342,5 +342,10 @@ public class WalletScreenController implements
|
|||||||
public CharSequence getLabel() {
|
public CharSequence getLabel() {
|
||||||
return mWalletCard.getCardLabel();
|
return mWalletCard.getCardLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PendingIntent getPendingIntent() {
|
||||||
|
return mWalletCard.getPendingIntent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,12 @@ import static com.android.systemui.wallet.ui.WalletCardCarousel.CARD_ANIM_ALPHA_
|
|||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.animation.AnimationUtils;
|
import android.view.animation.AnimationUtils;
|
||||||
@@ -46,10 +45,10 @@ import java.util.List;
|
|||||||
/** Layout for the wallet screen. */
|
/** Layout for the wallet screen. */
|
||||||
public class WalletView extends FrameLayout implements WalletCardCarousel.OnCardScrollListener {
|
public class WalletView extends FrameLayout implements WalletCardCarousel.OnCardScrollListener {
|
||||||
|
|
||||||
|
private static final String TAG = "WalletView";
|
||||||
private static final int CAROUSEL_IN_ANIMATION_DURATION = 300;
|
private static final int CAROUSEL_IN_ANIMATION_DURATION = 300;
|
||||||
private static final int CAROUSEL_OUT_ANIMATION_DURATION = 200;
|
private static final int CAROUSEL_OUT_ANIMATION_DURATION = 200;
|
||||||
private static final int CARD_LABEL_ANIM_DELAY = 133;
|
private static final int CARD_LABEL_ANIM_DELAY = 133;
|
||||||
private static final int CONTACTLESS_ICON_SIZE = 90;
|
|
||||||
|
|
||||||
private final WalletCardCarousel mCardCarousel;
|
private final WalletCardCarousel mCardCarousel;
|
||||||
private final ImageView mIcon;
|
private final ImageView mIcon;
|
||||||
@@ -65,6 +64,8 @@ public class WalletView extends FrameLayout implements WalletCardCarousel.OnCard
|
|||||||
private final TextView mErrorView;
|
private final TextView mErrorView;
|
||||||
private final ViewGroup mEmptyStateView;
|
private final ViewGroup mEmptyStateView;
|
||||||
private CharSequence mCenterCardText;
|
private CharSequence mCenterCardText;
|
||||||
|
private Drawable mCenterCardIcon;
|
||||||
|
private boolean mIsDeviceLocked = false;
|
||||||
|
|
||||||
public WalletView(Context context) {
|
public WalletView(Context context) {
|
||||||
this(context, null);
|
this(context, null);
|
||||||
@@ -104,16 +105,21 @@ public class WalletView extends FrameLayout implements WalletCardCarousel.OnCard
|
|||||||
@Override
|
@Override
|
||||||
public void onCardScroll(WalletCardViewInfo centerCard, WalletCardViewInfo nextCard,
|
public void onCardScroll(WalletCardViewInfo centerCard, WalletCardViewInfo nextCard,
|
||||||
float percentDistanceFromCenter) {
|
float percentDistanceFromCenter) {
|
||||||
CharSequence centerCardText = centerCard.getLabel();
|
CharSequence centerCardText = getLabelText(centerCard);
|
||||||
|
Drawable centerCardIcon = centerCard.getIcon();
|
||||||
if (!TextUtils.equals(mCenterCardText, centerCardText)) {
|
if (!TextUtils.equals(mCenterCardText, centerCardText)) {
|
||||||
mCenterCardText = centerCardText;
|
mCenterCardText = centerCardText;
|
||||||
|
mCenterCardIcon = centerCardIcon;
|
||||||
mCardLabel.setText(centerCardText);
|
mCardLabel.setText(centerCardText);
|
||||||
|
mIcon.setImageDrawable(centerCardIcon);
|
||||||
}
|
}
|
||||||
if (TextUtils.equals(centerCardText, nextCard.getLabel())) {
|
renderActionButton(centerCard, mIsDeviceLocked);
|
||||||
|
if (TextUtils.equals(centerCardText, getLabelText(nextCard))) {
|
||||||
mCardLabel.setAlpha(1f);
|
mCardLabel.setAlpha(1f);
|
||||||
} else {
|
} else {
|
||||||
mCardLabel.setAlpha(percentDistanceFromCenter);
|
mCardLabel.setAlpha(percentDistanceFromCenter);
|
||||||
mIcon.setAlpha(percentDistanceFromCenter);
|
mIcon.setAlpha(percentDistanceFromCenter);
|
||||||
|
mActionButton.setAlpha(percentDistanceFromCenter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,10 +134,11 @@ public class WalletView extends FrameLayout implements WalletCardCarousel.OnCard
|
|||||||
*/
|
*/
|
||||||
void showCardCarousel(
|
void showCardCarousel(
|
||||||
List<WalletCardViewInfo> data, int selectedIndex, boolean isDeviceLocked) {
|
List<WalletCardViewInfo> data, int selectedIndex, boolean isDeviceLocked) {
|
||||||
|
mIsDeviceLocked = isDeviceLocked;
|
||||||
boolean shouldAnimate = mCardCarousel.setData(data, selectedIndex);
|
boolean shouldAnimate = mCardCarousel.setData(data, selectedIndex);
|
||||||
mCardCarouselContainer.setVisibility(VISIBLE);
|
mCardCarouselContainer.setVisibility(VISIBLE);
|
||||||
mErrorView.setVisibility(GONE);
|
mErrorView.setVisibility(GONE);
|
||||||
renderHeaderIconAndActionButton(data.get(0), isDeviceLocked);
|
renderHeaderIconAndActionButton(data.get(selectedIndex), isDeviceLocked);
|
||||||
if (shouldAnimate) {
|
if (shouldAnimate) {
|
||||||
// If the empty state is visible, animate it away and delay the card carousel animation
|
// If the empty state is visible, animate it away and delay the card carousel animation
|
||||||
int emptyStateAnimDelay = 0;
|
int emptyStateAnimDelay = 0;
|
||||||
@@ -239,39 +246,45 @@ public class WalletView extends FrameLayout implements WalletCardCarousel.OnCard
|
|||||||
return mCardCarouselContainer;
|
return mCardCarouselContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
TextView getCardLabel() {
|
||||||
|
return mCardLabel;
|
||||||
|
}
|
||||||
|
|
||||||
private void renderHeaderIconAndActionButton(WalletCardViewInfo walletCard, boolean isLocked) {
|
private void renderHeaderIconAndActionButton(WalletCardViewInfo walletCard, boolean isLocked) {
|
||||||
Drawable icon = resizeDrawable(getResources(), walletCard.getIcon());
|
mIcon.setImageDrawable(walletCard.getIcon());
|
||||||
renderHeaderIcon(icon, isLocked);
|
mIcon.setVisibility(VISIBLE);
|
||||||
if (isLocked) {
|
renderActionButton(walletCard, isLocked);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderActionButton(WalletCardViewInfo walletCard, boolean isDeviceLocked) {
|
||||||
|
CharSequence actionButtonText = getActionButtonText(walletCard);
|
||||||
|
if (isDeviceLocked) {
|
||||||
mActionButton.setVisibility(VISIBLE);
|
mActionButton.setVisibility(VISIBLE);
|
||||||
mActionButton.setText(R.string.wallet_action_button_label_unlock);
|
mActionButton.setText(R.string.wallet_action_button_label_unlock);
|
||||||
|
} else if (actionButtonText != null) {
|
||||||
|
mActionButton.setText(actionButtonText);
|
||||||
|
mActionButton.setVisibility(VISIBLE);
|
||||||
|
mActionButton.setOnClickListener(v -> {
|
||||||
|
try {
|
||||||
|
walletCard.getPendingIntent().send();
|
||||||
|
} catch (PendingIntent.CanceledException e) {
|
||||||
|
Log.w(TAG, "Error sending pending intent for wallet card");
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
mActionButton.setVisibility(GONE);
|
mActionButton.setVisibility(GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderHeaderIcon(@Nullable Drawable icon, boolean isLocked) {
|
private static CharSequence getLabelText(WalletCardViewInfo card) {
|
||||||
if (icon == null) {
|
String[] rawLabel = card.getLabel().toString().split("\\n");
|
||||||
mIcon.setVisibility(INVISIBLE);
|
return rawLabel.length == 2 ? rawLabel[0] : card.getLabel();
|
||||||
return;
|
|
||||||
}
|
|
||||||
icon.setTint(mContext.getColor(isLocked ? R.color.GM2_grey_800 : R.color.GM2_blue_600));
|
|
||||||
mIcon.setImageDrawable(icon);
|
|
||||||
mIcon.setVisibility(VISIBLE);
|
|
||||||
mIcon.setBackground(
|
|
||||||
mContext.getDrawable(
|
|
||||||
isLocked
|
|
||||||
? R.drawable.circle_wallet_secondary_56dp
|
|
||||||
: R.drawable.circle_wallet_primary_56dp));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static Drawable resizeDrawable(Resources resources, @Nullable Drawable drawable) {
|
private static CharSequence getActionButtonText(WalletCardViewInfo card) {
|
||||||
if (drawable == null) {
|
String[] rawLabel = card.getLabel().toString().split("\\n");
|
||||||
return null;
|
return rawLabel.length == 2 ? rawLabel[1] : null;
|
||||||
}
|
|
||||||
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
|
|
||||||
return new BitmapDrawable(resources, Bitmap.createScaledBitmap(
|
|
||||||
bitmap, CONTACTLESS_ICON_SIZE, CONTACTLESS_ICON_SIZE, true));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
|
|||||||
|
|
||||||
assertEquals(Tile.STATE_ACTIVE, state.state);
|
assertEquals(Tile.STATE_ACTIVE, state.state);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
mContext.getString(R.string.wallet_secondary_label_active),
|
"•••• 1234",
|
||||||
state.secondaryLabel);
|
state.secondaryLabel);
|
||||||
assertNotNull(state.stateDescription);
|
assertNotNull(state.stateDescription);
|
||||||
assertNotNull(state.sideViewDrawable);
|
assertNotNull(state.sideViewDrawable);
|
||||||
@@ -332,7 +332,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
|
|||||||
assertEquals(
|
assertEquals(
|
||||||
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_height),
|
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_height),
|
||||||
request.getCardHeightPx());
|
request.getCardHeightPx());
|
||||||
assertEquals(2, request.getMaxCards());
|
assertEquals(1, request.getMaxCards());
|
||||||
assertThat(mCallbackCaptor.getValue()).isInstanceOf(
|
assertThat(mCallbackCaptor.getValue()).isInstanceOf(
|
||||||
QuickAccessWalletClient.OnWalletCardsRetrievedCallback.class);
|
QuickAccessWalletClient.OnWalletCardsRetrievedCallback.class);
|
||||||
}
|
}
|
||||||
@@ -423,6 +423,6 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
|
|||||||
private WalletCard createWalletCard(Context context) {
|
private WalletCard createWalletCard(Context context) {
|
||||||
PendingIntent pendingIntent =
|
PendingIntent pendingIntent =
|
||||||
PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
|
PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||||
return new WalletCard.Builder(CARD_ID, CARD_IMAGE, "description", pendingIntent).build();
|
return new WalletCard.Builder(CARD_ID, CARD_IMAGE, "•••• 1234", pendingIntent).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,13 @@ import static android.view.View.GONE;
|
|||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
@@ -50,6 +51,7 @@ import androidx.test.filters.SmallTest;
|
|||||||
|
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.plugins.ActivityStarter;
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
|
import com.android.systemui.plugins.FalsingManager;
|
||||||
import com.android.systemui.settings.UserTracker;
|
import com.android.systemui.settings.UserTracker;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
|
|
||||||
@@ -72,7 +74,8 @@ public class WalletScreenControllerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
private static final int MAX_CARDS = 10;
|
private static final int MAX_CARDS = 10;
|
||||||
private static final int CARD_CAROUSEL_WIDTH = 10;
|
private static final int CARD_CAROUSEL_WIDTH = 10;
|
||||||
private static final String CARD_ID = "card_id";
|
private static final String CARD_ID_1 = "card_id_1";
|
||||||
|
private static final String CARD_ID_2 = "card_id_2";
|
||||||
private static final CharSequence SHORTCUT_SHORT_LABEL = "View all";
|
private static final CharSequence SHORTCUT_SHORT_LABEL = "View all";
|
||||||
private static final CharSequence SHORTCUT_LONG_LABEL = "Add a payment method";
|
private static final CharSequence SHORTCUT_LONG_LABEL = "Add a payment method";
|
||||||
private static final CharSequence SERVICE_LABEL = "Wallet app";
|
private static final CharSequence SERVICE_LABEL = "Wallet app";
|
||||||
@@ -89,6 +92,8 @@ public class WalletScreenControllerTest extends SysuiTestCase {
|
|||||||
@Mock
|
@Mock
|
||||||
UserTracker mUserTracker;
|
UserTracker mUserTracker;
|
||||||
@Mock
|
@Mock
|
||||||
|
FalsingManager mFalsingManager;
|
||||||
|
@Mock
|
||||||
KeyguardStateController mKeyguardStateController;
|
KeyguardStateController mKeyguardStateController;
|
||||||
@Captor
|
@Captor
|
||||||
ArgumentCaptor<Intent> mIntentCaptor;
|
ArgumentCaptor<Intent> mIntentCaptor;
|
||||||
@@ -122,11 +127,12 @@ public class WalletScreenControllerTest extends SysuiTestCase {
|
|||||||
MoreExecutors.directExecutor(),
|
MoreExecutors.directExecutor(),
|
||||||
new Handler(mTestableLooper.getLooper()),
|
new Handler(mTestableLooper.getLooper()),
|
||||||
mUserTracker,
|
mUserTracker,
|
||||||
|
mFalsingManager,
|
||||||
mKeyguardStateController);
|
mKeyguardStateController);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void queryCards_hasCards_showCarousel() {
|
public void queryCards_hasCards_showCarousel_activeCard() {
|
||||||
GetWalletCardsResponse response =
|
GetWalletCardsResponse response =
|
||||||
new GetWalletCardsResponse(
|
new GetWalletCardsResponse(
|
||||||
Collections.singletonList(createWalletCard(mContext)), 0);
|
Collections.singletonList(createWalletCard(mContext)), 0);
|
||||||
@@ -145,6 +151,33 @@ public class WalletScreenControllerTest extends SysuiTestCase {
|
|||||||
mTestableLooper.processAllMessages();
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
assertEquals(VISIBLE, mWalletView.getCardCarouselContainer().getVisibility());
|
assertEquals(VISIBLE, mWalletView.getCardCarouselContainer().getVisibility());
|
||||||
|
assertEquals("Hold to reader", mWalletView.getCardLabel().getText().toString());
|
||||||
|
assertEquals(GONE, mWalletView.getErrorView().getVisibility());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryCards_hasCards_showCarousel_pendingActivationCard_parseLabel() {
|
||||||
|
GetWalletCardsResponse response =
|
||||||
|
new GetWalletCardsResponse(
|
||||||
|
Collections.singletonList(createNonActiveWalletCard(mContext)), 0);
|
||||||
|
|
||||||
|
mController.queryWalletCards();
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
|
verify(mWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture());
|
||||||
|
|
||||||
|
QuickAccessWalletClient.OnWalletCardsRetrievedCallback callback =
|
||||||
|
mCallbackCaptor.getValue();
|
||||||
|
|
||||||
|
assertEquals(mController, callback);
|
||||||
|
|
||||||
|
callback.onWalletCardsRetrieved(response);
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
|
assertEquals(VISIBLE, mWalletView.getCardCarouselContainer().getVisibility());
|
||||||
|
assertEquals("Not set up", mWalletView.getCardLabel().getText().toString());
|
||||||
|
assertEquals("Verify now", mWalletView.getActionButton().getText().toString());
|
||||||
|
assertEquals(VISIBLE, mWalletView.getActionButton().getVisibility());
|
||||||
assertEquals(GONE, mWalletView.getErrorView().getVisibility());
|
assertEquals(GONE, mWalletView.getErrorView().getVisibility());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +218,7 @@ public class WalletScreenControllerTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onWalletServiceEvent_nfcPaymentStart_dismiss() {
|
public void onWalletServiceEvent_nfcPaymentStart_doNothing() {
|
||||||
WalletServiceEvent event =
|
WalletServiceEvent event =
|
||||||
new WalletServiceEvent(WalletServiceEvent.TYPE_NFC_PAYMENT_STARTED);
|
new WalletServiceEvent(WalletServiceEvent.TYPE_NFC_PAYMENT_STARTED);
|
||||||
|
|
||||||
@@ -193,8 +226,8 @@ public class WalletScreenControllerTest extends SysuiTestCase {
|
|||||||
mTestableLooper.processAllMessages();
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
assertNull(mController.mSelectedCardId);
|
assertNull(mController.mSelectedCardId);
|
||||||
assertTrue(mController.mIsDismissed);
|
assertFalse(mController.mIsDismissed);
|
||||||
verify(mWalletClient).notifyWalletDismissed();
|
verifyZeroInteractions(mWalletClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -228,14 +261,14 @@ public class WalletScreenControllerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onCardSelected() {
|
public void onCardSelected() {
|
||||||
mController.onCardSelected(createCardViewInfo());
|
mController.onCardSelected(createCardViewInfo(createWalletCard(mContext)));
|
||||||
|
|
||||||
assertEquals(CARD_ID, mController.mSelectedCardId);
|
assertEquals(CARD_ID_1, mController.mSelectedCardId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onCardClicked_startIntent() {
|
public void onCardClicked_startIntent() {
|
||||||
WalletCardViewInfo walletCardViewInfo = createCardViewInfo();
|
WalletCardViewInfo walletCardViewInfo = createCardViewInfo(createWalletCard(mContext));
|
||||||
|
|
||||||
mController.onCardClicked(walletCardViewInfo);
|
mController.onCardClicked(walletCardViewInfo);
|
||||||
|
|
||||||
@@ -278,18 +311,30 @@ public class WalletScreenControllerTest extends SysuiTestCase {
|
|||||||
assertEquals(GONE, mWalletView.getVisibility());
|
assertEquals(GONE, mWalletView.getVisibility());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WalletCard createNonActiveWalletCard(Context context) {
|
||||||
|
PendingIntent pendingIntent =
|
||||||
|
PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||||
|
return new WalletCard.Builder(CARD_ID_2, createIcon(), "•••• 5678", pendingIntent)
|
||||||
|
.setCardIcon(createIcon())
|
||||||
|
.setCardLabel("Not set up\nVerify now")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
private WalletCard createWalletCard(Context context) {
|
private WalletCard createWalletCard(Context context) {
|
||||||
PendingIntent pendingIntent =
|
PendingIntent pendingIntent =
|
||||||
PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
|
PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||||
return new WalletCard.Builder(CARD_ID, createIcon(), "description", pendingIntent).build();
|
return new WalletCard.Builder(CARD_ID_1, createIcon(), "•••• 1234", pendingIntent)
|
||||||
|
.setCardIcon(createIcon())
|
||||||
|
.setCardLabel("Hold to reader")
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Icon createIcon() {
|
private static Icon createIcon() {
|
||||||
return Icon.createWithBitmap(Bitmap.createBitmap(70, 44, Bitmap.Config.ARGB_8888));
|
return Icon.createWithBitmap(Bitmap.createBitmap(70, 44, Bitmap.Config.ARGB_8888));
|
||||||
}
|
}
|
||||||
|
|
||||||
private WalletCardViewInfo createCardViewInfo() {
|
private WalletCardViewInfo createCardViewInfo(WalletCard walletCard) {
|
||||||
return new WalletScreenController.QAWalletCardViewInfo(
|
return new WalletScreenController.QAWalletCardViewInfo(
|
||||||
mContext, createWalletCard(mContext));
|
mContext, walletCard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user