Merge "Recreate QuickAccessWallet for Wallet Tile and Lockscreen Icon when the default payment app has changed." into sc-dev

This commit is contained in:
TreeHugger Robot
2021-05-26 20:50:05 +00:00
committed by Android (Google) Code Review
8 changed files with 454 additions and 141 deletions

View File

@@ -18,13 +18,14 @@ package com.android.systemui.qs.tiles;
import static android.provider.Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT; import static android.provider.Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT;
import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.service.quickaccesswallet.GetWalletCardsError; import android.service.quickaccesswallet.GetWalletCardsError;
import android.service.quickaccesswallet.GetWalletCardsRequest;
import android.service.quickaccesswallet.GetWalletCardsResponse; import android.service.quickaccesswallet.GetWalletCardsResponse;
import android.service.quickaccesswallet.QuickAccessWalletClient; import android.service.quickaccesswallet.QuickAccessWalletClient;
import android.service.quickaccesswallet.WalletCard; import android.service.quickaccesswallet.WalletCard;
@@ -51,6 +52,7 @@ import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
import com.android.systemui.wallet.ui.WalletActivity; import com.android.systemui.wallet.ui.WalletActivity;
import java.util.List; import java.util.List;
@@ -66,16 +68,15 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
private final CharSequence mLabel = mContext.getString(R.string.wallet_title); private final CharSequence mLabel = mContext.getString(R.string.wallet_title);
private final WalletCardRetriever mCardRetriever = new WalletCardRetriever(); private final WalletCardRetriever mCardRetriever = new WalletCardRetriever();
// TODO(b/180959290): Re-create the QAW Client when the default NFC payment app changes.
private final QuickAccessWalletClient mQuickAccessWalletClient;
private final KeyguardStateController mKeyguardStateController; private final KeyguardStateController mKeyguardStateController;
private final PackageManager mPackageManager; private final PackageManager mPackageManager;
private final SecureSettings mSecureSettings; private final SecureSettings mSecureSettings;
private final Executor mExecutor; private final Executor mExecutor;
private final QuickAccessWalletController mController;
private final FeatureFlags mFeatureFlags; private final FeatureFlags mFeatureFlags;
@VisibleForTesting Drawable mCardViewDrawable;
private WalletCard mSelectedCard; private WalletCard mSelectedCard;
@VisibleForTesting Drawable mCardViewDrawable;
@Inject @Inject
public QuickAccessWalletTile( public QuickAccessWalletTile(
@@ -87,15 +88,15 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
StatusBarStateController statusBarStateController, StatusBarStateController statusBarStateController,
ActivityStarter activityStarter, ActivityStarter activityStarter,
QSLogger qsLogger, QSLogger qsLogger,
QuickAccessWalletClient quickAccessWalletClient,
KeyguardStateController keyguardStateController, KeyguardStateController keyguardStateController,
PackageManager packageManager, PackageManager packageManager,
SecureSettings secureSettings, SecureSettings secureSettings,
@Background Executor executor, @Main Executor executor,
QuickAccessWalletController quickAccessWalletController,
FeatureFlags featureFlags) { FeatureFlags featureFlags) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger); statusBarStateController, activityStarter, qsLogger);
mQuickAccessWalletClient = quickAccessWalletClient; mController = quickAccessWalletController;
mKeyguardStateController = keyguardStateController; mKeyguardStateController = keyguardStateController;
mPackageManager = packageManager; mPackageManager = packageManager;
mSecureSettings = secureSettings; mSecureSettings = secureSettings;
@@ -115,7 +116,11 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
protected void handleSetListening(boolean listening) { protected void handleSetListening(boolean listening) {
super.handleSetListening(listening); super.handleSetListening(listening);
if (listening) { if (listening) {
queryWalletCards(); mController.setupWalletChangeObservers(mCardRetriever, DEFAULT_PAYMENT_APP_CHANGE);
if (!mController.getWalletClient().isWalletServiceAvailable()) {
mController.reCreateWalletClient();
}
mController.queryWalletCards(mCardRetriever);
} }
} }
@@ -139,12 +144,13 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
mContext.startActivity(intent); mContext.startActivity(intent);
} }
} else { } else {
if (mQuickAccessWalletClient.createWalletIntent() == null) { if (mController.getWalletClient().createWalletIntent() == null) {
Log.w(TAG, "Could not get intent of the wallet app."); Log.w(TAG, "Could not get intent of the wallet app.");
return; return;
} }
mActivityStarter.postStartActivityDismissingKeyguard( mActivityStarter.postStartActivityDismissingKeyguard(
mQuickAccessWalletClient.createWalletIntent(), /* delay= */ 0, mController.getWalletClient().createWalletIntent(),
/* delay= */ 0,
animationController); animationController);
} }
}); });
@@ -152,30 +158,34 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
@Override @Override
protected void handleUpdateState(State state, Object arg) { protected void handleUpdateState(State state, Object arg) {
CharSequence label = mQuickAccessWalletClient.getServiceLabel(); CharSequence label = mController.getWalletClient().getServiceLabel();
state.label = label == null ? mLabel : label; state.label = label == null ? mLabel : label;
state.contentDescription = state.label; state.contentDescription = state.label;
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 (mController.getWalletClient().isWalletServiceAvailable()) {
if (mSelectedCard != null) { 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);
state.sideViewCustomDrawable = null;
} else { } else {
state.state = Tile.STATE_ACTIVE; state.state = Tile.STATE_ACTIVE;
state.secondaryLabel = mSelectedCard.getContentDescription(); state.secondaryLabel = mSelectedCard.getContentDescription();
state.sideViewCustomDrawable = mCardViewDrawable;
} }
} else { } else {
state.state = Tile.STATE_INACTIVE; state.state = Tile.STATE_INACTIVE;
state.secondaryLabel = mContext.getString(R.string.wallet_secondary_label_no_card); state.secondaryLabel = mContext.getString(R.string.wallet_secondary_label_no_card);
state.sideViewCustomDrawable = null;
} }
state.stateDescription = state.secondaryLabel; state.stateDescription = state.secondaryLabel;
} else { } else {
state.state = Tile.STATE_UNAVAILABLE; state.state = Tile.STATE_UNAVAILABLE;
state.secondaryLabel = null;
state.sideViewCustomDrawable = null;
} }
state.sideViewCustomDrawable = isDeviceLocked ? null : mCardViewDrawable;
} }
@Override @Override
@@ -198,19 +208,14 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
@Override @Override
public CharSequence getTileLabel() { public CharSequence getTileLabel() {
CharSequence label = mQuickAccessWalletClient.getServiceLabel(); CharSequence label = mController.getWalletClient().getServiceLabel();
return label == null ? mLabel : label; return label == null ? mLabel : label;
} }
private void queryWalletCards() { @Override
int cardWidth = protected void handleDestroy() {
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_width); super.handleDestroy();
int cardHeight = mController.unregisterWalletChangeObservers(DEFAULT_PAYMENT_APP_CHANGE);
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_height);
int iconSizePx = mContext.getResources().getDimensionPixelSize(R.dimen.wallet_icon_size);
GetWalletCardsRequest request =
new GetWalletCardsRequest(cardWidth, cardHeight, iconSizePx, /* maxCards= */ 1);
mQuickAccessWalletClient.getWalletCards(mExecutor, request, mCardRetriever);
} }
private class WalletCardRetriever implements private class WalletCardRetriever implements

View File

@@ -24,6 +24,8 @@ import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_BUTT
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK; import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK;
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON; import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON;
import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_UNLOCK; import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_UNLOCK;
import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE;
import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.ActivityOptions; import android.app.ActivityOptions;
@@ -39,7 +41,6 @@ import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
@@ -49,13 +50,10 @@ import android.os.Messenger;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.provider.Settings;
import android.service.media.CameraPrewarmService; import android.service.media.CameraPrewarmService;
import android.service.quickaccesswallet.GetWalletCardsError; import android.service.quickaccesswallet.GetWalletCardsError;
import android.service.quickaccesswallet.GetWalletCardsRequest;
import android.service.quickaccesswallet.GetWalletCardsResponse; import android.service.quickaccesswallet.GetWalletCardsResponse;
import android.service.quickaccesswallet.QuickAccessWalletClient; import android.service.quickaccesswallet.QuickAccessWalletClient;
import android.service.quickaccesswallet.QuickAccessWalletClientImpl;
import android.telecom.TelecomManager; import android.telecom.TelecomManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
@@ -71,7 +69,6 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils;
@@ -97,11 +94,9 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.PreviewInflater; import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.tuner.LockscreenFragment.LockButtonFactory; import com.android.systemui.tuner.LockscreenFragment.LockButtonFactory;
import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.wallet.controller.QuickAccessWalletController;
import com.android.systemui.wallet.ui.WalletActivity; import com.android.systemui.wallet.ui.WalletActivity;
import java.util.concurrent.Executor;
/** /**
* Implementation for the bottom area of the Keyguard, including camera/phone affordance and status * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
* text. * text.
@@ -137,10 +132,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private KeyguardAffordanceView mLeftAffordanceView; private KeyguardAffordanceView mLeftAffordanceView;
private ImageView mWalletButton; private ImageView mWalletButton;
private boolean mWalletEnabled = false;
private boolean mHasCard = false; private boolean mHasCard = false;
private WalletCardRetriever mCardRetriever = new WalletCardRetriever(); private WalletCardRetriever mCardRetriever = new WalletCardRetriever();
private QuickAccessWalletClient mQuickAccessWalletClient; private QuickAccessWalletController mQuickAccessWalletController;
private ViewGroup mIndicationArea; private ViewGroup mIndicationArea;
private TextView mIndicationText; private TextView mIndicationText;
@@ -159,7 +153,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private StatusBar mStatusBar; private StatusBar mStatusBar;
private KeyguardAffordanceHelper mAffordanceHelper; private KeyguardAffordanceHelper mAffordanceHelper;
private FalsingManager mFalsingManager; private FalsingManager mFalsingManager;
@Nullable private Executor mUiExecutor;
private boolean mUserSetupComplete; private boolean mUserSetupComplete;
private boolean mPrewarmBound; private boolean mPrewarmBound;
private Messenger mPrewarmMessenger; private Messenger mPrewarmMessenger;
@@ -193,8 +186,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private int mBurnInYOffset; private int mBurnInYOffset;
private ActivityIntentHelper mActivityIntentHelper; private ActivityIntentHelper mActivityIntentHelper;
private KeyguardUpdateMonitor mKeyguardUpdateMonitor; private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private ContentObserver mWalletPreferenceObserver;
private SecureSettings mSecureSettings;
public KeyguardBottomAreaView(Context context) { public KeyguardBottomAreaView(Context context) {
this(context, null); this(context, null);
@@ -332,8 +323,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
getContext().unregisterReceiver(mDevicePolicyReceiver); getContext().unregisterReceiver(mDevicePolicyReceiver);
mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback); mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
if (mWalletPreferenceObserver != null) { if (mQuickAccessWalletController != null) {
mSecureSettings.unregisterContentObserver(mWalletPreferenceObserver); mQuickAccessWalletController.unregisterWalletChangeObservers(
WALLET_PREFERENCE_CHANGE, DEFAULT_PAYMENT_APP_CHANGE);
} }
} }
@@ -456,7 +448,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
} }
private void updateWalletVisibility() { private void updateWalletVisibility() {
if (mDozing || !mWalletEnabled || !mHasCard) { if (mDozing
|| mQuickAccessWalletController == null
|| !mQuickAccessWalletController.isWalletEnabled()
|| !mHasCard) {
mWalletButton.setVisibility(GONE); mWalletButton.setVisibility(GONE);
mIndicationArea.setPadding(0, 0, 0, 0); mIndicationArea.setPadding(0, 0, 0, 0);
} else { } else {
@@ -690,7 +685,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
@Override @Override
public void onKeyguardShowingChanged() { public void onKeyguardShowingChanged() {
if (mKeyguardStateController.isShowing()) { if (mKeyguardStateController.isShowing()) {
queryWalletCards(); if (mQuickAccessWalletController != null) {
mQuickAccessWalletController.queryWalletCards(mCardRetriever);
}
} }
} }
@@ -935,50 +932,17 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
/** /**
* Initialize the wallet feature, only enabling if the feature is enabled within the platform. * Initialize the wallet feature, only enabling if the feature is enabled within the platform.
*/ */
public void initWallet(QuickAccessWalletClient client, Executor uiExecutor, public void initWallet(
SecureSettings secureSettings) { QuickAccessWalletController controller) {
mQuickAccessWalletClient = client; mQuickAccessWalletController = controller;
mSecureSettings = secureSettings; mQuickAccessWalletController.setupWalletChangeObservers(
setupWalletPreferenceObserver(); mCardRetriever, WALLET_PREFERENCE_CHANGE, DEFAULT_PAYMENT_APP_CHANGE);
updateWalletPreference(); mQuickAccessWalletController.updateWalletPreference();
mQuickAccessWalletController.queryWalletCards(mCardRetriever);
mUiExecutor = uiExecutor;
queryWalletCards();
updateWalletVisibility(); updateWalletVisibility();
} }
private void setupWalletPreferenceObserver() {
if (mWalletPreferenceObserver == null) {
mWalletPreferenceObserver = new ContentObserver(null /* handler */) {
@Override
public void onChange(boolean selfChange) {
mUiExecutor.execute(() -> updateWalletPreference());
}
};
mSecureSettings.registerContentObserver(
Settings.Secure.getUriFor(QuickAccessWalletClientImpl.SETTING_KEY),
false /* notifyForDescendants */,
mWalletPreferenceObserver);
}
}
private void updateWalletPreference() {
mWalletEnabled = mQuickAccessWalletClient.isWalletFeatureAvailable()
&& mQuickAccessWalletClient.isWalletFeatureAvailableWhenDeviceLocked();
}
private void queryWalletCards() {
if (!mWalletEnabled || mUiExecutor == null) {
return;
}
GetWalletCardsRequest request =
new GetWalletCardsRequest(1 /* cardWidth */, 1 /* cardHeight */,
1 /* iconSizePx */, 1 /* maxCards */);
mQuickAccessWalletClient.getWalletCards(mUiExecutor, request, mCardRetriever);
}
private void onWalletClick(View v) { private void onWalletClick(View v) {
// More coming here; need to inform the user about how to proceed // More coming here; need to inform the user about how to proceed
if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
@@ -991,12 +955,13 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent); mContext.startActivity(intent);
} else { } else {
if (mQuickAccessWalletClient.createWalletIntent() == null) { if (mQuickAccessWalletController.getWalletClient().createWalletIntent() == null) {
Log.w(TAG, "Could not get intent of the wallet app."); Log.w(TAG, "Could not get intent of the wallet app.");
return; return;
} }
mActivityStarter.postStartActivityDismissingKeyguard( mActivityStarter.postStartActivityDismissingKeyguard(
mQuickAccessWalletClient.createWalletIntent(), /* delay= */ 0); mQuickAccessWalletController.getWalletClient().createWalletIntent(),
/* delay= */ 0);
} }
} }

View File

@@ -54,7 +54,6 @@ import android.os.PowerManager;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.UserManager; import android.os.UserManager;
import android.os.VibrationEffect; import android.os.VibrationEffect;
import android.service.quickaccesswallet.QuickAccessWalletClient;
import android.util.Log; import android.util.Log;
import android.util.MathUtils; import android.util.MathUtils;
import android.view.DisplayCutout; import android.view.DisplayCutout;
@@ -153,6 +152,7 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.util.Utils; import com.android.systemui.util.Utils;
import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
import com.android.wm.shell.animation.FlingAnimationUtils; import com.android.wm.shell.animation.FlingAnimationUtils;
import java.io.FileDescriptor; import java.io.FileDescriptor;
@@ -310,6 +310,7 @@ public class NotificationPanelViewController extends PanelViewController {
private final FeatureFlags mFeatureFlags; private final FeatureFlags mFeatureFlags;
private final ScrimController mScrimController; private final ScrimController mScrimController;
private final PrivacyDotViewController mPrivacyDotViewController; private final PrivacyDotViewController mPrivacyDotViewController;
private final QuickAccessWalletController mQuickAccessWalletController;
// Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow card. // Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow card.
// If there are exactly 1 + mMaxKeyguardNotifications, then still shows all notifications // If there are exactly 1 + mMaxKeyguardNotifications, then still shows all notifications
@@ -584,7 +585,6 @@ public class NotificationPanelViewController extends PanelViewController {
private int mNotificationScrimPadding; private int mNotificationScrimPadding;
private boolean mQSAnimatingHiddenFromCollapsed; private boolean mQSAnimatingHiddenFromCollapsed;
private final QuickAccessWalletClient mQuickAccessWalletClient;
private final Executor mUiExecutor; private final Executor mUiExecutor;
private final SecureSettings mSecureSettings; private final SecureSettings mSecureSettings;
@@ -665,11 +665,11 @@ public class NotificationPanelViewController extends PanelViewController {
AmbientState ambientState, AmbientState ambientState,
LockIconViewController lockIconViewController, LockIconViewController lockIconViewController,
FeatureFlags featureFlags, FeatureFlags featureFlags,
QuickAccessWalletClient quickAccessWalletClient,
KeyguardMediaController keyguardMediaController, KeyguardMediaController keyguardMediaController,
PrivacyDotViewController privacyDotViewController, PrivacyDotViewController privacyDotViewController,
TapAgainViewController tapAgainViewController, TapAgainViewController tapAgainViewController,
FragmentService fragmentService, FragmentService fragmentService,
QuickAccessWalletController quickAccessWalletController,
@Main Executor uiExecutor, @Main Executor uiExecutor,
SecureSettings secureSettings) { SecureSettings secureSettings) {
super(view, falsingManager, dozeLog, keyguardStateController, super(view, falsingManager, dozeLog, keyguardStateController,
@@ -680,6 +680,7 @@ public class NotificationPanelViewController extends PanelViewController {
mVibratorHelper = vibratorHelper; mVibratorHelper = vibratorHelper;
mKeyguardMediaController = keyguardMediaController; mKeyguardMediaController = keyguardMediaController;
mPrivacyDotViewController = privacyDotViewController; mPrivacyDotViewController = privacyDotViewController;
mQuickAccessWalletController = quickAccessWalletController;
mMetricsLogger = metricsLogger; mMetricsLogger = metricsLogger;
mActivityManager = activityManager; mActivityManager = activityManager;
mConfigurationController = configurationController; mConfigurationController = configurationController;
@@ -722,7 +723,6 @@ public class NotificationPanelViewController extends PanelViewController {
mScrimController.setClipsQsScrim(!mShouldUseSplitNotificationShade); mScrimController.setClipsQsScrim(!mShouldUseSplitNotificationShade);
mUserManager = userManager; mUserManager = userManager;
mMediaDataManager = mediaDataManager; mMediaDataManager = mediaDataManager;
mQuickAccessWalletClient = quickAccessWalletClient;
mTapAgainViewController = tapAgainViewController; mTapAgainViewController = tapAgainViewController;
mUiExecutor = uiExecutor; mUiExecutor = uiExecutor;
mSecureSettings = secureSettings; mSecureSettings = secureSettings;
@@ -1123,7 +1123,7 @@ public class NotificationPanelViewController extends PanelViewController {
mKeyguardBottomArea.setFalsingManager(mFalsingManager); mKeyguardBottomArea.setFalsingManager(mFalsingManager);
if (mFeatureFlags.isQuickAccessWalletEnabled()) { if (mFeatureFlags.isQuickAccessWalletEnabled()) {
mKeyguardBottomArea.initWallet(mQuickAccessWalletClient, mUiExecutor, mSecureSettings); mKeyguardBottomArea.initWallet(mQuickAccessWalletController);
} }
} }

View File

@@ -0,0 +1,207 @@
/*
* Copyright (C) 2021 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.
*/
package com.android.systemui.wallet.controller;
import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE;
import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE;
import android.content.Context;
import android.database.ContentObserver;
import android.provider.Settings;
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.util.settings.SecureSettings;
import java.util.concurrent.Executor;
import javax.inject.Inject;
/**
* Controller to handle communication between SystemUI and Quick Access Wallet Client.
*/
@SysUISingleton
public class QuickAccessWalletController {
/**
* Event for the wallet status change, e.g. the default payment app change and the wallet
* preference change.
*/
public enum WalletChangeEvent {
DEFAULT_PAYMENT_APP_CHANGE,
WALLET_PREFERENCE_CHANGE,
}
private static final String TAG = "QAWController";
private final Context mContext;
private final Executor mExecutor;
private final SecureSettings mSecureSettings;
private QuickAccessWalletClient mQuickAccessWalletClient;
private ContentObserver mWalletPreferenceObserver;
private ContentObserver mDefaultPaymentAppObserver;
private int mWalletPreferenceChangeEvents = 0;
private int mDefaultPaymentAppChangeEvents = 0;
private boolean mWalletEnabled = false;
@Inject
public QuickAccessWalletController(
Context context,
@Main Executor executor,
SecureSettings secureSettings,
QuickAccessWalletClient quickAccessWalletClient) {
mContext = context;
mExecutor = executor;
mSecureSettings = secureSettings;
mQuickAccessWalletClient = quickAccessWalletClient;
}
/**
* Returns true if the Quick Access Wallet service & feature is available.
*/
public boolean isWalletEnabled() {
return mWalletEnabled;
}
/**
* Returns the current instance of {@link QuickAccessWalletClient} in the controller.
*/
public QuickAccessWalletClient getWalletClient() {
return mQuickAccessWalletClient;
}
/**
* Setup the wallet change observers per {@link WalletChangeEvent}
*
* @param cardsRetriever a callback that retrieves the wallet cards
* @param events {@link WalletChangeEvent} need to be handled.
*/
public void setupWalletChangeObservers(
QuickAccessWalletClient.OnWalletCardsRetrievedCallback cardsRetriever,
WalletChangeEvent... events) {
for (WalletChangeEvent event : events) {
if (event == WALLET_PREFERENCE_CHANGE) {
setupWalletPreferenceObserver();
} else if (event == DEFAULT_PAYMENT_APP_CHANGE) {
setupDefaultPaymentAppObserver(cardsRetriever);
}
}
}
/**
* Unregister wallet change observers per {@link WalletChangeEvent} if needed.
*
*/
public void unregisterWalletChangeObservers(WalletChangeEvent... events) {
for (WalletChangeEvent event : events) {
if (event == WALLET_PREFERENCE_CHANGE && mWalletPreferenceObserver != null) {
mWalletPreferenceChangeEvents--;
if (mWalletPreferenceChangeEvents == 0) {
mSecureSettings.unregisterContentObserver(mWalletPreferenceObserver);
}
} else if (event == DEFAULT_PAYMENT_APP_CHANGE && mDefaultPaymentAppObserver != null) {
mDefaultPaymentAppChangeEvents--;
if (mDefaultPaymentAppChangeEvents == 0) {
mSecureSettings.unregisterContentObserver(mDefaultPaymentAppObserver);
}
}
}
}
/**
* Update the "show wallet" preference.
*/
public void updateWalletPreference() {
mWalletEnabled = mQuickAccessWalletClient.isWalletServiceAvailable()
&& mQuickAccessWalletClient.isWalletFeatureAvailable()
&& mQuickAccessWalletClient.isWalletFeatureAvailableWhenDeviceLocked();
}
/**
* Query the wallet cards from {@link QuickAccessWalletClient}.
*
* @param cardsRetriever a callback to retrieve wallet cards.
*/
public void queryWalletCards(
QuickAccessWalletClient.OnWalletCardsRetrievedCallback cardsRetriever) {
if (!mWalletEnabled) {
Log.w(TAG, "QuickAccessWallet is unavailable, unable to query cards.");
return;
}
int cardWidth =
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_width);
int cardHeight =
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_height);
int iconSizePx = mContext.getResources().getDimensionPixelSize(R.dimen.wallet_icon_size);
GetWalletCardsRequest request =
new GetWalletCardsRequest(cardWidth, cardHeight, iconSizePx, /* maxCards= */ 1);
mQuickAccessWalletClient.getWalletCards(mExecutor, request, cardsRetriever);
}
/**
* Re-create the {@link QuickAccessWalletClient} of the controller.
*/
public void reCreateWalletClient() {
mQuickAccessWalletClient = QuickAccessWalletClient.create(mContext);
}
private void setupDefaultPaymentAppObserver(
QuickAccessWalletClient.OnWalletCardsRetrievedCallback cardsRetriever) {
if (mDefaultPaymentAppObserver == null) {
mDefaultPaymentAppObserver = new ContentObserver(null /* handler */) {
@Override
public void onChange(boolean selfChange) {
mExecutor.execute(() -> {
reCreateWalletClient();
updateWalletPreference();
queryWalletCards(cardsRetriever);
});
}
};
mSecureSettings.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT),
false /* notifyForDescendants */,
mDefaultPaymentAppObserver);
}
mDefaultPaymentAppChangeEvents++;
}
private void setupWalletPreferenceObserver() {
if (mWalletPreferenceObserver == null) {
mWalletPreferenceObserver = new ContentObserver(null /* handler */) {
@Override
public void onChange(boolean selfChange) {
mExecutor.execute(() -> {
updateWalletPreference();
});
}
};
mSecureSettings.registerContentObserver(
Settings.Secure.getUriFor(QuickAccessWalletClientImpl.SETTING_KEY),
false /* notifyForDescendants */,
mWalletPreferenceObserver);
}
mWalletPreferenceChangeEvents++;
}
}

View File

@@ -24,6 +24,7 @@ import android.graphics.drawable.Drawable;
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.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.Window; import android.view.Window;
@@ -52,7 +53,7 @@ import javax.inject.Inject;
*/ */
public class WalletActivity extends LifecycleActivity { public class WalletActivity extends LifecycleActivity {
private final QuickAccessWalletClient mQuickAccessWalletClient; private static final String TAG = "WalletActivity";
private final KeyguardStateController mKeyguardStateController; private final KeyguardStateController mKeyguardStateController;
private final KeyguardDismissUtil mKeyguardDismissUtil; private final KeyguardDismissUtil mKeyguardDismissUtil;
private final ActivityStarter mActivityStarter; private final ActivityStarter mActivityStarter;
@@ -65,7 +66,6 @@ public class WalletActivity extends LifecycleActivity {
@Inject @Inject
public WalletActivity( public WalletActivity(
QuickAccessWalletClient quickAccessWalletClient,
KeyguardStateController keyguardStateController, KeyguardStateController keyguardStateController,
KeyguardDismissUtil keyguardDismissUtil, KeyguardDismissUtil keyguardDismissUtil,
ActivityStarter activityStarter, ActivityStarter activityStarter,
@@ -74,7 +74,6 @@ public class WalletActivity extends LifecycleActivity {
FalsingManager falsingManager, FalsingManager falsingManager,
UserTracker userTracker, UserTracker userTracker,
StatusBarKeyguardViewManager keyguardViewManager) { StatusBarKeyguardViewManager keyguardViewManager) {
mQuickAccessWalletClient = quickAccessWalletClient;
mKeyguardStateController = keyguardStateController; mKeyguardStateController = keyguardStateController;
mKeyguardDismissUtil = keyguardDismissUtil; mKeyguardDismissUtil = keyguardDismissUtil;
mActivityStarter = activityStarter; mActivityStarter = activityStarter;
@@ -103,10 +102,11 @@ public class WalletActivity extends LifecycleActivity {
getActionBar().setHomeActionContentDescription(R.string.accessibility_desc_close); getActionBar().setHomeActionContentDescription(R.string.accessibility_desc_close);
WalletView walletView = requireViewById(R.id.wallet_view); WalletView walletView = requireViewById(R.id.wallet_view);
QuickAccessWalletClient walletClient = QuickAccessWalletClient.create(this);
mWalletScreenController = new WalletScreenController( mWalletScreenController = new WalletScreenController(
this, this,
walletView, walletView,
mQuickAccessWalletClient, walletClient,
mActivityStarter, mActivityStarter,
mExecutor, mExecutor,
mHandler, mHandler,
@@ -116,6 +116,10 @@ public class WalletActivity extends LifecycleActivity {
walletView.getAppButton().setOnClickListener( walletView.getAppButton().setOnClickListener(
v -> { v -> {
if (walletClient.createWalletIntent() == null) {
Log.w(TAG, "Unable to create wallet app intent.");
return;
}
if (!mKeyguardStateController.isUnlocked() if (!mKeyguardStateController.isUnlocked()
&& mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { && mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
return; return;
@@ -123,12 +127,12 @@ public class WalletActivity extends LifecycleActivity {
if (mKeyguardStateController.isUnlocked()) { if (mKeyguardStateController.isUnlocked()) {
mActivityStarter.startActivity( mActivityStarter.startActivity(
mQuickAccessWalletClient.createWalletIntent(), true); walletClient.createWalletIntent(), true);
finish(); finish();
} else { } else {
mKeyguardDismissUtil.executeWhenUnlocked(() -> { mKeyguardDismissUtil.executeWhenUnlocked(() -> {
mActivityStarter.startActivity( mActivityStarter.startActivity(
mQuickAccessWalletClient.createWalletIntent(), true); walletClient.createWalletIntent(), true);
finish(); finish();
return false; return false;
}, false, true); }, false, true);

View File

@@ -73,6 +73,7 @@ import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.MoreExecutors;
@@ -119,6 +120,8 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
@Mock @Mock
private SecureSettings mSecureSettings; private SecureSettings mSecureSettings;
@Mock @Mock
private QuickAccessWalletController mController;
@Mock
private FeatureFlags mFeatureFlags; private FeatureFlags mFeatureFlags;
@Captor @Captor
ArgumentCaptor<Intent> mIntentCaptor; ArgumentCaptor<Intent> mIntentCaptor;
@@ -145,6 +148,8 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
when(mQuickAccessWalletClient.getServiceLabel()).thenReturn(LABEL); when(mQuickAccessWalletClient.getServiceLabel()).thenReturn(LABEL);
when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true); when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true);
when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(true); when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(true);
when(mQuickAccessWalletClient.isWalletFeatureAvailableWhenDeviceLocked()).thenReturn(true);
when(mController.getWalletClient()).thenReturn(mQuickAccessWalletClient);
mTile = new QuickAccessWalletTile( mTile = new QuickAccessWalletTile(
mHost, mHost,
@@ -155,11 +160,11 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
mStatusBarStateController, mStatusBarStateController,
mActivityStarter, mActivityStarter,
mQSLogger, mQSLogger,
mQuickAccessWalletClient,
mKeyguardStateController, mKeyguardStateController,
mPackageManager, mPackageManager,
mSecureSettings, mSecureSettings,
MoreExecutors.directExecutor(), MoreExecutors.directExecutor(),
mController,
mFeatureFlags); mFeatureFlags);
} }
@@ -174,6 +179,15 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
assertFalse(mTile.isAvailable()); assertFalse(mTile.isAvailable());
} }
@Test
public void testWalletServiceUnavailable_recreateWalletClient() {
when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(false);
mTile.handleSetListening(true);
verify(mController, times(1)).reCreateWalletClient();
}
@Test @Test
public void testIsAvailable_qawFeatureAvailable() { public void testIsAvailable_qawFeatureAvailable() {
when(mPackageManager.hasSystemFeature(FEATURE_NFC_HOST_CARD_EMULATION)).thenReturn(true); when(mPackageManager.hasSystemFeature(FEATURE_NFC_HOST_CARD_EMULATION)).thenReturn(true);
@@ -330,17 +344,8 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
public void testHandleSetListening_queryCards() { public void testHandleSetListening_queryCards() {
mTile.handleSetListening(true); mTile.handleSetListening(true);
verify(mQuickAccessWalletClient) verify(mController).queryWalletCards(mCallbackCaptor.capture());
.getWalletCards(any(), mRequestCaptor.capture(), mCallbackCaptor.capture());
GetWalletCardsRequest request = mRequestCaptor.getValue();
assertEquals(
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_width),
request.getCardWidthPx());
assertEquals(
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_height),
request.getCardHeightPx());
assertEquals(1, request.getMaxCards());
assertThat(mCallbackCaptor.getValue()).isInstanceOf( assertThat(mCallbackCaptor.getValue()).isInstanceOf(
QuickAccessWalletClient.OnWalletCardsRetrievedCallback.class); QuickAccessWalletClient.OnWalletCardsRetrievedCallback.class);
} }
@@ -353,37 +358,6 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
assertNotNull(mTile.getState().sideViewCustomDrawable); assertNotNull(mTile.getState().sideViewCustomDrawable);
} }
@Test
public void testState_queryCards_hasCards_then_noCards() {
when(mKeyguardStateController.isUnlocked()).thenReturn(true);
GetWalletCardsResponse responseWithCards =
new GetWalletCardsResponse(
Collections.singletonList(createWalletCard(mContext)), 0);
GetWalletCardsResponse responseWithoutCards =
new GetWalletCardsResponse(Collections.EMPTY_LIST, 0);
mTile.handleSetListening(true);
verify(mQuickAccessWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture());
// query wallet cards, has cards
mCallbackCaptor.getValue().onWalletCardsRetrieved(responseWithCards);
mTestableLooper.processAllMessages();
assertNotNull(mTile.getState().sideViewCustomDrawable);
mTile.handleSetListening(true);
verify(mQuickAccessWalletClient, times(2))
.getWalletCards(any(), any(), mCallbackCaptor.capture());
// query wallet cards, has no cards
mCallbackCaptor.getValue().onWalletCardsRetrieved(responseWithoutCards);
mTestableLooper.processAllMessages();
assertNull(mTile.getState().sideViewCustomDrawable);
}
@Test @Test
public void testQueryCards_noCards_notUpdateSideViewDrawable() { public void testQueryCards_noCards_notUpdateSideViewDrawable() {
setUpWalletCard(/* hasCard= */ false); setUpWalletCard(/* hasCard= */ false);
@@ -398,7 +372,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
mTile.handleSetListening(true); mTile.handleSetListening(true);
verify(mQuickAccessWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture()); verify(mController).queryWalletCards(mCallbackCaptor.capture());
mCallbackCaptor.getValue().onWalletCardRetrievalError(error); mCallbackCaptor.getValue().onWalletCardRetrievalError(error);
mTestableLooper.processAllMessages(); mTestableLooper.processAllMessages();
@@ -422,7 +396,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
mTile.handleSetListening(true); mTile.handleSetListening(true);
verify(mQuickAccessWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture()); verify(mController).queryWalletCards(mCallbackCaptor.capture());
mCallbackCaptor.getValue().onWalletCardsRetrieved(response); mCallbackCaptor.getValue().onWalletCardsRetrieved(response);
mTestableLooper.processAllMessages(); mTestableLooper.processAllMessages();

View File

@@ -42,7 +42,6 @@ import android.content.res.Resources;
import android.hardware.biometrics.BiometricSourceType; import android.hardware.biometrics.BiometricSourceType;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.UserManager; import android.os.UserManager;
import android.service.quickaccesswallet.QuickAccessWalletClient;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper; import android.testing.TestableLooper;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
@@ -112,6 +111,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.time.FakeSystemClock; import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.wallet.controller.QuickAccessWalletController;
import com.android.wm.shell.animation.FlingAnimationUtils; import com.android.wm.shell.animation.FlingAnimationUtils;
import org.junit.Before; import org.junit.Before;
@@ -252,8 +252,6 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Mock @Mock
private LockIconViewController mLockIconViewController; private LockIconViewController mLockIconViewController;
@Mock @Mock
private QuickAccessWalletClient mQuickAccessWalletClient;
@Mock
private KeyguardMediaController mKeyguardMediaController; private KeyguardMediaController mKeyguardMediaController;
@Mock @Mock
private PrivacyDotViewController mPrivacyDotViewController; private PrivacyDotViewController mPrivacyDotViewController;
@@ -267,6 +265,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
private FragmentService mFragmentService; private FragmentService mFragmentService;
@Mock @Mock
private FragmentHostManager mFragmentHostManager; private FragmentHostManager mFragmentHostManager;
@Mock
private QuickAccessWalletController mQuickAccessWalletController;
private SysuiStatusBarStateController mStatusBarStateController; private SysuiStatusBarStateController mStatusBarStateController;
private NotificationPanelViewController mNotificationPanelViewController; private NotificationPanelViewController mNotificationPanelViewController;
@@ -380,11 +380,11 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mAmbientState, mAmbientState,
mLockIconViewController, mLockIconViewController,
mFeatureFlags, mFeatureFlags,
mQuickAccessWalletClient,
mKeyguardMediaController, mKeyguardMediaController,
mPrivacyDotViewController, mPrivacyDotViewController,
mTapAgainViewController, mTapAgainViewController,
mFragmentService, mFragmentService,
mQuickAccessWalletController,
new FakeExecutor(new FakeSystemClock()), new FakeExecutor(new FakeSystemClock()),
mSecureSettings); mSecureSettings);
mNotificationPanelViewController.initDependencies( mNotificationPanelViewController.initDependencies(

View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2021 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.
*/
package com.android.systemui.wallet.controller;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
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;
import android.service.quickaccesswallet.GetWalletCardsRequest;
import android.service.quickaccesswallet.QuickAccessWalletClient;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.util.settings.SecureSettings;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
public class QuickAccessWalletControllerTest extends SysuiTestCase {
@Mock
private QuickAccessWalletClient mQuickAccessWalletClient;
@Mock
private SecureSettings mSecureSettings;
@Mock
private QuickAccessWalletClient.OnWalletCardsRetrievedCallback mCardsRetriever;
@Captor
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);
mController = new QuickAccessWalletController(
mContext,
MoreExecutors.directExecutor(),
mSecureSettings,
mQuickAccessWalletClient);
}
@Test
public void walletEnabled() {
mController.updateWalletPreference();
assertTrue(mController.isWalletEnabled());
}
@Test
public void walletServiceUnavailable_walletNotEnabled() {
when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(false);
mController.updateWalletPreference();
assertFalse(mController.isWalletEnabled());
}
@Test
public void walletFeatureUnavailable_walletNotEnabled() {
when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(false);
mController.updateWalletPreference();
assertFalse(mController.isWalletEnabled());
}
@Test
public void walletFeatureWhenLockedUnavailable_walletNotEnabled() {
when(mQuickAccessWalletClient.isWalletFeatureAvailableWhenDeviceLocked()).thenReturn(false);
mController.updateWalletPreference();
assertFalse(mController.isWalletEnabled());
}
@Test
public void getWalletClient_NoRecreation_sameClient() {
assertSame(mQuickAccessWalletClient, mController.getWalletClient());
}
@Test
public void getWalletClient_reCreateClient_notSameClient() {
mController.reCreateWalletClient();
assertNotSame(mQuickAccessWalletClient, mController.getWalletClient());
}
@Test
public void queryWalletCards_walletNotEnabled_notQuery() {
when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(false);
mController.queryWalletCards(mCardsRetriever);
verify(mQuickAccessWalletClient, never()).getWalletCards(any(), any(), any());
}
@Test
public void queryWalletCards_walletEnabled_queryCards() {
mController.updateWalletPreference();
mController.queryWalletCards(mCardsRetriever);
verify(mQuickAccessWalletClient)
.getWalletCards(
eq(MoreExecutors.directExecutor()),
mRequestCaptor.capture(),
eq(mCardsRetriever));
GetWalletCardsRequest request = mRequestCaptor.getValue();
assertEquals(1, mRequestCaptor.getValue().getMaxCards());
assertEquals(
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_width),
request.getCardWidthPx());
assertEquals(
mContext.getResources().getDimensionPixelSize(R.dimen.wallet_tile_card_view_height),
request.getCardHeightPx());
}
}