diff --git a/core/api/current.txt b/core/api/current.txt index 0e82509c1ddc9..48ab51d6e8a69 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 @@ -38995,6 +38996,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 4132c64a44c9a..5bd6ca827e293 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 ee70be442d163..0dca78d890a51 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 f37b930aabcec..1b69ca12da3a1 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 f69c89d453126..38659e12b1cec 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; @@ -152,6 +153,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 @@ -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 2d0faad8cb13d..95b51ea4dece9 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 mRequestQueue; private final Map 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 @@ -246,6 +245,25 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser return createIntent(walletActivity, packageName, ACTION_VIEW_WALLET); } + @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() { @@ -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 db20a51e23ed2..70ccd6fbd590f 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 0d290eee5777d..cf4be739e05af 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 d774fd4e397a7..68ed8c962ba9a 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -8821,7 +8821,8 @@ - + +