summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Scottie Biddle <scottieb@google.com> 2022-01-18 21:33:38 +0000
committer Scottie Biddle <scottieb@google.com> 2022-02-07 12:56:39 -0800
commit21d16aecd77919f1d3f2588230016ffbfa415bba (patch)
treedc6d07608c7cecd9fc4e8707e3f35ff8302644c4
parent2262a4a733ee73a4e49efcad4f1cbeda595d3ea9 (diff)
Add new config and API for QuickAccessWallet features.
Adds a new configuration attribute for use in QuickAccessWalletService: * useTargetActivityForQuickAccess - this is a boolean, false by default. When true, the system will use the component specified by the android:targetActivity attribute instead of the SysUi's WalletActivity. Adds a new API method to QuickAccessWalletService: the method returns a PendingIntent that can be used in place of the targetActivity specified in the service's manifest entry. The method is not abstract; by default it returns null so that existing services will not have to make any changes to target android T. To make use of this feature, define a new method in QuickAccessWalletClient: useTargetActivityForQuickAccess() which provides the configuration for use by QuickAccessWalletController. Updates QuickAccessWalletController to define a new method: startQuickAccessUiIntent(), which reads the configuration as well as whether the service is providing any cards, and provides a centralized place to launch the correct Quick Access intent. The logic there is: 1. If a PendingIntent is provided from the service, use that. 2. If not, check for an active activity from the metadata in XML. 3. If that isn't available OR useTargetActivityForQuickAccess is false and the system is displaying cards, use WalletActivity provided by SystemUi. Addes tests for QuickAccessWalletController. CTS Test for QuickAccessWalletClient has new tests in a separate change in the same topic. In the course of development, discovered that unit tests for QuickAccessWalletController has been failing for as long as a year. Will fix that and update in a follow-up. Test: atest QuickAccessWalletControllerTest Test: atest QuickAccessWalletClientTest Bug: 215725263 Change-Id: Ifa3427d5e6f6b02e4afffa40453d1cb0f4f8ed67
-rw-r--r--core/api/current.txt2
-rw-r--r--core/api/test-current.txt6
-rw-r--r--core/java/android/service/quickaccesswallet/IQuickAccessWalletService.aidl4
-rw-r--r--core/java/android/service/quickaccesswallet/IQuickAccessWalletServiceCallbacks.aidl3
-rw-r--r--core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java27
-rw-r--r--core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java37
-rw-r--r--core/java/android/service/quickaccesswallet/QuickAccessWalletService.java23
-rw-r--r--core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java16
-rw-r--r--core/res/res/values/attrs.xml3
-rw-r--r--core/res/res/values/public.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java84
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java77
12 files changed, 270 insertions, 13 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 058861a214b9..cbc9f48616d2 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -1642,6 +1642,7 @@ package android {
field public static final int useEmbeddedDex = 16844190; // 0x101059e
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
field public static final int useLevel = 16843167; // 0x101019f
+ field public static final int useTargetActivityForQuickAccess;
field public static final int userVisible = 16843409; // 0x1010291
field public static final int usesCleartextTraffic = 16844012; // 0x10104ec
field public static final int usesPermissionFlags = 16844356; // 0x1010644
@@ -38990,6 +38991,7 @@ package android.service.quickaccesswallet {
public abstract class QuickAccessWalletService extends android.app.Service {
ctor public QuickAccessWalletService();
+ method @Nullable public android.app.PendingIntent getTargetActivityPendingIntent();
method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onWalletCardSelected(@NonNull android.service.quickaccesswallet.SelectWalletCardRequest);
method public abstract void onWalletCardsRequested(@NonNull android.service.quickaccesswallet.GetWalletCardsRequest, @NonNull android.service.quickaccesswallet.GetWalletCardsCallback);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 4132c64a44c9..5bd6ca827e29 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2357,12 +2357,14 @@ package android.service.quickaccesswallet {
method public void disconnect();
method public void getWalletCards(@NonNull android.service.quickaccesswallet.GetWalletCardsRequest, @NonNull android.service.quickaccesswallet.QuickAccessWalletClient.OnWalletCardsRetrievedCallback);
method public void getWalletCards(@NonNull java.util.concurrent.Executor, @NonNull android.service.quickaccesswallet.GetWalletCardsRequest, @NonNull android.service.quickaccesswallet.QuickAccessWalletClient.OnWalletCardsRetrievedCallback);
+ method public void getWalletPendingIntent(@NonNull java.util.concurrent.Executor, @NonNull android.service.quickaccesswallet.QuickAccessWalletClient.WalletPendingIntentCallback);
method public boolean isWalletFeatureAvailable();
method public boolean isWalletFeatureAvailableWhenDeviceLocked();
method public boolean isWalletServiceAvailable();
method public void notifyWalletDismissed();
method public void removeWalletServiceEventListener(@NonNull android.service.quickaccesswallet.QuickAccessWalletClient.WalletServiceEventListener);
method public void selectWalletCard(@NonNull android.service.quickaccesswallet.SelectWalletCardRequest);
+ method public boolean useTargetActivityForQuickAccess();
}
public static interface QuickAccessWalletClient.OnWalletCardsRetrievedCallback {
@@ -2370,6 +2372,10 @@ package android.service.quickaccesswallet {
method public void onWalletCardsRetrieved(@NonNull android.service.quickaccesswallet.GetWalletCardsResponse);
}
+ public static interface QuickAccessWalletClient.WalletPendingIntentCallback {
+ method public void onWalletPendingIntentRetrieved(@Nullable android.app.PendingIntent);
+ }
+
public static interface QuickAccessWalletClient.WalletServiceEventListener {
method public void onWalletServiceEvent(@NonNull android.service.quickaccesswallet.WalletServiceEvent);
}
diff --git a/core/java/android/service/quickaccesswallet/IQuickAccessWalletService.aidl b/core/java/android/service/quickaccesswallet/IQuickAccessWalletService.aidl
index ee70be442d16..0dca78d890a5 100644
--- a/core/java/android/service/quickaccesswallet/IQuickAccessWalletService.aidl
+++ b/core/java/android/service/quickaccesswallet/IQuickAccessWalletService.aidl
@@ -41,4 +41,6 @@ interface IQuickAccessWalletService {
in IQuickAccessWalletServiceCallbacks callback);
// Unregister an event listener
oneway void unregisterWalletServiceEventListener(in WalletServiceEventListenerRequest request);
-} \ No newline at end of file
+ // Request to get a PendingIntent to launch an activity from which the user can manage their cards.
+ oneway void onTargetActivityIntentRequested(in IQuickAccessWalletServiceCallbacks callbacks);
+ } \ No newline at end of file
diff --git a/core/java/android/service/quickaccesswallet/IQuickAccessWalletServiceCallbacks.aidl b/core/java/android/service/quickaccesswallet/IQuickAccessWalletServiceCallbacks.aidl
index f37b930aabce..1b69ca12da3a 100644
--- a/core/java/android/service/quickaccesswallet/IQuickAccessWalletServiceCallbacks.aidl
+++ b/core/java/android/service/quickaccesswallet/IQuickAccessWalletServiceCallbacks.aidl
@@ -16,6 +16,7 @@
package android.service.quickaccesswallet;
+import android.app.PendingIntent;
import android.service.quickaccesswallet.GetWalletCardsError;
import android.service.quickaccesswallet.GetWalletCardsResponse;
import android.service.quickaccesswallet.WalletServiceEvent;
@@ -34,4 +35,6 @@ interface IQuickAccessWalletServiceCallbacks {
// Called in response to registerWalletServiceEventListener. May be called multiple times as
// long as the event listener is registered.
oneway void onWalletServiceEvent(in WalletServiceEvent event);
+ // Called in response to onTargetActivityIntentRequested. May only be called once per request.
+ oneway void onTargetActivityPendingIntentReceived(in PendingIntent pendingIntent);
} \ No newline at end of file
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java
index f69c89d45312..38659e12b1ce 100644
--- a/core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java
@@ -20,6 +20,7 @@ import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
@@ -153,6 +154,21 @@ public interface QuickAccessWalletClient extends Closeable {
void disconnect();
/**
+ * The QuickAccessWalletService may provide a {@link PendingIntent} to start the activity that
+ * hosts the Wallet view. This is typically the home screen of the Wallet application. If this
+ * method returns null, the value returned by getWalletIntent() will be used instead.
+ */
+ void getWalletPendingIntent(@NonNull @CallbackExecutor Executor executor,
+ @NonNull WalletPendingIntentCallback walletPendingIntentCallback);
+
+ /**
+ * Callback for getWalletPendingIntent.
+ */
+ interface WalletPendingIntentCallback {
+ void onWalletPendingIntentRetrieved(@Nullable PendingIntent walletPendingIntent);
+ }
+
+ /**
* The manifest entry for the QuickAccessWalletService may also publish information about the
* activity that hosts the Wallet view. This is typically the home screen of the Wallet
* application.
@@ -212,4 +228,15 @@ public interface QuickAccessWalletClient extends Closeable {
*/
@Nullable
CharSequence getShortcutLongLabel();
+
+ /**
+ * Return whether the system should use the component specified by the
+ * {@link android:targetActivity} or
+ * {@link QuickAccessWalletService#getTargetActivityPendingIntent()}
+ * as the "quick access" , invoked directly by the system.
+ * If false, the system will use the built-in UI instead of the component specified
+ * in {@link android:targetActivity} or
+ * {@link QuickAccessWalletService#getTargetActivityPendingIntent()}.
+ */
+ boolean useTargetActivityForQuickAccess();
}
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
index 2d0faad8cb13..95b51ea4dece 100644
--- a/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java
@@ -24,6 +24,7 @@ import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -67,10 +68,9 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
private final Queue<ApiCaller> mRequestQueue;
private final Map<WalletServiceEventListener, String> mEventListeners;
private boolean mIsConnected;
- /**
- * Timeout for active service connections (1 minute)
- */
+ /** Timeout for active service connections (1 minute) */
private static final long SERVICE_CONNECTION_TIMEOUT_MS = 60 * 1000;
+
@Nullable
private IQuickAccessWalletService mService;
@@ -146,7 +146,6 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
serviceCallback.onGetWalletCardsFailure(new GetWalletCardsError(null, null));
}
});
-
}
@Override
@@ -247,6 +246,25 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
}
@Override
+ public void getWalletPendingIntent(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull WalletPendingIntentCallback pendingIntentCallback) {
+ BaseCallbacks callbacks = new BaseCallbacks() {
+ @Override
+ public void onTargetActivityPendingIntentReceived(PendingIntent pendingIntent) {
+ executor.execute(
+ () -> pendingIntentCallback.onWalletPendingIntentRetrieved(pendingIntent));
+ }
+ };
+ executeApiCall(new ApiCaller("getTargetActivityPendingIntent") {
+ @Override
+ void performApiCall(IQuickAccessWalletService service) throws RemoteException {
+ service.onTargetActivityIntentRequested(callbacks);
+ }
+ });
+ }
+
+ @Override
@Nullable
public Intent createWalletSettingsIntent() {
if (mServiceInfo == null) {
@@ -330,6 +348,11 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
return mServiceInfo == null ? null : mServiceInfo.getShortcutLongLabel(mContext);
}
+ @Override
+ public boolean useTargetActivityForQuickAccess() {
+ return mServiceInfo.getUseTargetActivityForQuickAccess();
+ }
+
private void connect() {
mHandler.post(this::connectInternal);
}
@@ -388,7 +411,7 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
return;
}
mIsConnected = false;
- mContext.unbindService(/*conn=*/this);
+ mContext.unbindService(/*conn=*/ this);
mService = null;
mEventListeners.clear();
mRequestQueue.clear();
@@ -482,5 +505,9 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser
public void onWalletServiceEvent(WalletServiceEvent event) {
throw new IllegalStateException();
}
+
+ public void onTargetActivityPendingIntentReceived(PendingIntent pendingIntent) {
+ throw new IllegalStateException();
+ }
}
}
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
index db20a51e23ed..70ccd6fbd590 100644
--- a/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletService.java
@@ -19,6 +19,7 @@ package android.service.quickaccesswallet;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
+import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
@@ -238,6 +239,14 @@ public abstract class QuickAccessWalletService extends Service {
mHandler.post(QuickAccessWalletService.this::onWalletDismissed);
}
+ @Override
+ public void onTargetActivityIntentRequested(
+ @NonNull IQuickAccessWalletServiceCallbacks callbacks) {
+ mHandler.post(
+ () -> QuickAccessWalletService.this.onTargetActivityIntentRequestedInternal(
+ callbacks));
+ }
+
public void registerWalletServiceEventListener(
@NonNull WalletServiceEventListenerRequest request,
@NonNull IQuickAccessWalletServiceCallbacks callback) {
@@ -257,6 +266,15 @@ public abstract class QuickAccessWalletService extends Service {
new GetWalletCardsCallbackImpl(request, callback, mHandler));
}
+ private void onTargetActivityIntentRequestedInternal(
+ IQuickAccessWalletServiceCallbacks callbacks) {
+ try {
+ callbacks.onTargetActivityPendingIntentReceived(getTargetActivityPendingIntent());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error returning wallet cards", e);
+ }
+ }
+
@Override
@Nullable
public IBinder onBind(@NonNull Intent intent) {
@@ -318,6 +336,11 @@ public abstract class QuickAccessWalletService extends Service {
mHandler.post(() -> sendWalletServiceEventInternal(serviceEvent));
}
+ @Nullable
+ public PendingIntent getTargetActivityPendingIntent() {
+ return null;
+ }
+
private void sendWalletServiceEventInternal(WalletServiceEvent serviceEvent) {
if (mEventListener == null) {
Log.i(TAG, "No dismiss listener registered");
diff --git a/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java b/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java
index 0d290eee5777..cf4be739e05a 100644
--- a/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java
+++ b/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java
@@ -144,20 +144,23 @@ class QuickAccessWalletServiceInfo {
private final CharSequence mShortcutShortLabel;
@Nullable
private final CharSequence mShortcutLongLabel;
+ private final boolean mUseTargetActivityForQuickAccess;
private static ServiceMetadata empty() {
- return new ServiceMetadata(null, null, null, null);
+ return new ServiceMetadata(null, null, null, null, false);
}
private ServiceMetadata(
String targetActivity,
String settingsActivity,
CharSequence shortcutShortLabel,
- CharSequence shortcutLongLabel) {
+ CharSequence shortcutLongLabel,
+ boolean useTargetActivityForQuickAccess) {
mTargetActivity = targetActivity;
mSettingsActivity = settingsActivity;
mShortcutShortLabel = shortcutShortLabel;
mShortcutLongLabel = shortcutLongLabel;
+ mUseTargetActivityForQuickAccess = useTargetActivityForQuickAccess;
}
}
@@ -191,8 +194,11 @@ class QuickAccessWalletServiceInfo {
R.styleable.QuickAccessWalletService_shortcutShortLabel);
CharSequence shortcutLongLabel = afsAttributes.getText(
R.styleable.QuickAccessWalletService_shortcutLongLabel);
+ boolean useTargetActivityForQuickAccess = afsAttributes.getBoolean(
+ R.styleable.QuickAccessWalletService_useTargetActivityForQuickAccess,
+ false);
return new ServiceMetadata(targetActivity, settingsActivity, shortcutShortLabel,
- shortcutLongLabel);
+ shortcutLongLabel, useTargetActivityForQuickAccess);
} finally {
if (afsAttributes != null) {
afsAttributes.recycle();
@@ -271,4 +277,8 @@ class QuickAccessWalletServiceInfo {
CharSequence getServiceLabel(Context context) {
return mServiceInfo.loadLabel(context.getPackageManager());
}
+
+ boolean getUseTargetActivityForQuickAccess() {
+ return mServiceMetadata.mUseTargetActivityForQuickAccess;
+ }
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d774fd4e397a..68ed8c962ba9 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8821,7 +8821,8 @@
<attr name="shortcutLongLabel"/>
<!-- Text shown on the button that takes users to the wallet application -->
<attr name="shortcutShortLabel"/>
-
+ <!-- When true, launch the component specified in targetActivity for quick access -->
+ <attr name="useTargetActivityForQuickAccess" format="boolean"/>
</declare-styleable>
<!-- Use <code>recognition-service</code> as the root tag of the XML resource that
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d57f5ba8179b..c4bfef4ae57a 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3262,6 +3262,7 @@
<public name="allowGameFpsOverride" />
<public name="localeConfig" />
<public name="showBackground" />
+ <public name="useTargetActivityForQuickAccess"/>
<public name="inheritKeyStoreKeys" />
<public name="preferKeepClear" />
<public name="autoHandwritingEnabled" />
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
index 4a4f2e9710dd..70728902f621 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java
@@ -19,7 +19,10 @@ 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.annotation.CallbackExecutor;
+import android.app.PendingIntent;
import android.content.Context;
+import android.content.Intent;
import android.database.ContentObserver;
import android.provider.Settings;
import android.service.quickaccesswallet.GetWalletCardsRequest;
@@ -28,10 +31,13 @@ import android.service.quickaccesswallet.QuickAccessWalletClientImpl;
import android.util.Log;
import com.android.systemui.R;
+import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.time.SystemClock;
+import com.android.systemui.wallet.ui.WalletActivity;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -57,6 +63,7 @@ public class QuickAccessWalletController {
private static final long RECREATION_TIME_WINDOW = TimeUnit.MINUTES.toMillis(10L);
private final Context mContext;
private final Executor mExecutor;
+ private final Executor mCallbackExecutor;
private final SecureSettings mSecureSettings;
private final SystemClock mClock;
@@ -72,11 +79,13 @@ public class QuickAccessWalletController {
public QuickAccessWalletController(
Context context,
@Main Executor executor,
+ @CallbackExecutor Executor callbackExecutor,
SecureSettings secureSettings,
QuickAccessWalletClient quickAccessWalletClient,
SystemClock clock) {
mContext = context;
mExecutor = executor;
+ mCallbackExecutor = callbackExecutor;
mSecureSettings = secureSettings;
mQuickAccessWalletClient = quickAccessWalletClient;
mClock = clock;
@@ -117,7 +126,6 @@ public class QuickAccessWalletController {
/**
* Unregister wallet change observers per {@link WalletChangeEvent} if needed.
- *
*/
public void unregisterWalletChangeObservers(WalletChangeEvent... events) {
for (WalletChangeEvent event : events) {
@@ -178,6 +186,80 @@ public class QuickAccessWalletController {
mQawClientCreatedTimeMillis = mClock.elapsedRealtime();
}
+ /**
+ * Starts the QuickAccessWallet UI: either the app's designated UI, or the built-in Wallet UI.
+ *
+ * If the service has configured itself so that
+ * {@link QuickAccessWalletClient#useTargetActivityForQuickAccess()}
+ * is true, or the service isn't providing any cards, use the target activity. Otherwise, use
+ * the SysUi {@link WalletActivity}
+ *
+ * The Wallet target activity is defined as the {@link android.app.PendingIntent} returned by
+ * {@link QuickAccessWalletClient#getWalletPendingIntent} if that is not null. If that is null,
+ * then the {@link Intent} returned by {@link QuickAccessWalletClient#createWalletIntent()}. If
+ * that too is null, then fall back to {@link WalletActivity}.
+ *
+ * @param activityStarter an {@link ActivityStarter} to launch the Intent or PendingIntent.
+ * @param animationController an {@link ActivityLaunchAnimator.Controller} to provide a
+ * smooth animation for the activity launch.
+ * @param hasCard whether the service returns any cards.
+ */
+ public void startQuickAccessUiIntent(ActivityStarter activityStarter,
+ ActivityLaunchAnimator.Controller animationController,
+ boolean hasCard) {
+ if (mQuickAccessWalletClient.useTargetActivityForQuickAccess() || !hasCard) {
+ mQuickAccessWalletClient.getWalletPendingIntent(mCallbackExecutor,
+ walletPendingIntent -> {
+ if (walletPendingIntent == null) {
+ Intent intent = mQuickAccessWalletClient.createWalletIntent();
+ if (intent == null) {
+ intent = getSysUiWalletIntent();
+ }
+ startQuickAccessViaIntent(intent, hasCard, activityStarter,
+ animationController);
+ return;
+ }
+ startQuickAccessViaPendingIntent(walletPendingIntent,
+ activityStarter, animationController);
+ });
+ } else {
+ startQuickAccessViaIntent(getSysUiWalletIntent(),
+ hasCard,
+ activityStarter,
+ animationController);
+ }
+ }
+
+ private Intent getSysUiWalletIntent() {
+ return new Intent(mContext, WalletActivity.class)
+ .setAction(Intent.ACTION_VIEW);
+ }
+
+ private void startQuickAccessViaIntent(Intent intent,
+ boolean hasCard,
+ ActivityStarter activityStarter,
+ ActivityLaunchAnimator.Controller animationController) {
+ if (hasCard) {
+ activityStarter.startActivity(intent, true /* dismissShade */,
+ animationController, true /* showOverLockscreenWhenLocked */);
+ } else {
+ activityStarter.postStartActivityDismissingKeyguard(
+ intent,
+ /* delay= */ 0,
+ animationController);
+ }
+ }
+
+ private void startQuickAccessViaPendingIntent(PendingIntent pendingIntent,
+ ActivityStarter activityStarter,
+ ActivityLaunchAnimator.Controller animationController) {
+ activityStarter.postStartActivityDismissingKeyguard(
+ pendingIntent,
+ animationController);
+
+ }
+
+
private void setupDefaultPaymentAppObserver(
QuickAccessWalletClient.OnWalletCardsRetrievedCallback cardsRetriever) {
if (mDefaultPaymentAppObserver == null) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java
index 72a329a0f0ba..d8aef6668a27 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java
@@ -23,10 +23,13 @@ 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.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.PendingIntent;
+import android.content.Intent;
import android.service.quickaccesswallet.GetWalletCardsRequest;
import android.service.quickaccesswallet.QuickAccessWalletClient;
import android.testing.AndroidTestingRunner;
@@ -36,6 +39,8 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.ActivityLaunchAnimator;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.time.FakeSystemClock;
@@ -60,8 +65,16 @@ public class QuickAccessWalletControllerTest extends SysuiTestCase {
private SecureSettings mSecureSettings;
@Mock
private QuickAccessWalletClient.OnWalletCardsRetrievedCallback mCardsRetriever;
+ @Mock
+ private ActivityStarter mActivityStarter;
+ @Mock
+ private ActivityLaunchAnimator.Controller mAnimationController;
@Captor
private ArgumentCaptor<GetWalletCardsRequest> mRequestCaptor;
+ @Captor
+ private ArgumentCaptor<Intent> mIntentCaptor;
+ @Captor
+ private ArgumentCaptor<PendingIntent> mPendingIntentCaptor;
private FakeSystemClock mClock = new FakeSystemClock();
private QuickAccessWalletController mController;
@@ -69,14 +82,24 @@ public class QuickAccessWalletControllerTest extends SysuiTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+
when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(true);
when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true);
when(mQuickAccessWalletClient.isWalletFeatureAvailableWhenDeviceLocked()).thenReturn(true);
mClock.setElapsedRealtime(100L);
+ doAnswer(invocation -> {
+ QuickAccessWalletClient.WalletPendingIntentCallback callback =
+ (QuickAccessWalletClient.WalletPendingIntentCallback) invocation
+ .getArguments()[1];
+ callback.onWalletPendingIntentRetrieved(null);
+ return null;
+ }).when(mQuickAccessWalletClient).getWalletPendingIntent(any(), any());
+
mController = new QuickAccessWalletController(
mContext,
MoreExecutors.directExecutor(),
+ MoreExecutors.directExecutor(),
mSecureSettings,
mQuickAccessWalletClient,
mClock);
@@ -151,8 +174,7 @@ public class QuickAccessWalletControllerTest extends SysuiTestCase {
verify(mQuickAccessWalletClient)
.getWalletCards(
- eq(MoreExecutors.directExecutor()),
- mRequestCaptor.capture(),
+ eq(MoreExecutors.directExecutor()), mRequestCaptor.capture(),
eq(mCardsRetriever));
GetWalletCardsRequest request = mRequestCaptor.getValue();
@@ -173,4 +195,55 @@ public class QuickAccessWalletControllerTest extends SysuiTestCase {
verify(mQuickAccessWalletClient, never()).getWalletCards(any(), any(), any());
}
+
+ @Test
+ public void getQuickAccessUiIntent_hasCards_useTargetActivityFalse_startsWalletActivity() {
+ when(mQuickAccessWalletClient.useTargetActivityForQuickAccess()).thenReturn(false);
+ mController.startQuickAccessUiIntent(mActivityStarter, mAnimationController, true);
+ verify(mActivityStarter).startActivity(mIntentCaptor.capture(), eq(true),
+ any(ActivityLaunchAnimator.Controller.class), eq(true));
+ Intent intent = mIntentCaptor.getValue();
+ assertEquals(intent.getAction(), Intent.ACTION_VIEW);
+ assertEquals(
+ intent.getComponent().getClassName(),
+ "com.android.systemui.wallet.ui.WalletActivity");
+ }
+
+ @Test
+ public void getQuickAccessUiIntent_noCards_useTargetActivityFalse_isWalletActivity() {
+ when(mQuickAccessWalletClient.useTargetActivityForQuickAccess()).thenReturn(false);
+ mController.startQuickAccessUiIntent(mActivityStarter, mAnimationController, false);
+ verify(mActivityStarter).postStartActivityDismissingKeyguard(mIntentCaptor.capture(), eq(0),
+ any(ActivityLaunchAnimator.Controller.class));
+ Intent intent = mIntentCaptor.getValue();
+ assertEquals(intent.getAction(), Intent.ACTION_VIEW);
+ assertEquals(
+ intent.getComponent().getClassName(),
+ "com.android.systemui.wallet.ui.WalletActivity");
+ }
+
+ @Test
+ public void getQuickAccessUiIntent_targetActivityViaPendingIntent_intentComponentIsCorrect() {
+ doAnswer(invocation -> {
+ QuickAccessWalletClient.WalletPendingIntentCallback callback =
+ (QuickAccessWalletClient.WalletPendingIntentCallback) invocation
+ .getArguments()[1];
+ Intent intent = new Intent(Intent.ACTION_VIEW).setClassName(
+ "com.google.android.apps.testapp",
+ "com.google.android.apps.testapp.TestActivity");
+ callback.onWalletPendingIntentRetrieved(
+ PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_IMMUTABLE));
+ return null;
+ }).when(mQuickAccessWalletClient).getWalletPendingIntent(any(), any());
+ when(mQuickAccessWalletClient.useTargetActivityForQuickAccess()).thenReturn(true);
+ mController.startQuickAccessUiIntent(mActivityStarter, mAnimationController, true);
+ verify(mActivityStarter).postStartActivityDismissingKeyguard(mPendingIntentCaptor.capture(),
+ any(ActivityLaunchAnimator.Controller.class));
+ PendingIntent pendingIntent = mPendingIntentCaptor.getValue();
+ Intent intent = pendingIntent.getIntent();
+ assertEquals(intent.getAction(), Intent.ACTION_VIEW);
+ assertEquals(
+ intent.getComponent().getClassName(),
+ "com.google.android.apps.testapp.TestActivity");
+ }
}