Loading api/test-current.txt +3 −1 Original line number Diff line number Diff line Loading @@ -3435,13 +3435,15 @@ package android.service.notification { package android.service.quickaccesswallet { public interface QuickAccessWalletClient { public interface QuickAccessWalletClient extends java.io.Closeable { method public void addWalletServiceEventListener(@NonNull android.service.quickaccesswallet.QuickAccessWalletClient.WalletServiceEventListener); method public void addWalletServiceEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.service.quickaccesswallet.QuickAccessWalletClient.WalletServiceEventListener); method @NonNull public static android.service.quickaccesswallet.QuickAccessWalletClient create(@NonNull android.content.Context); method @Nullable public android.content.Intent createWalletIntent(); method @Nullable public android.content.Intent createWalletSettingsIntent(); 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 boolean isWalletFeatureAvailable(); method public boolean isWalletFeatureAvailableWhenDeviceLocked(); method public boolean isWalletServiceAvailable(); Loading core/java/android/service/quickaccesswallet/GetWalletCardsCallbackImpl.java +43 −24 Original line number Diff line number Diff line Loading @@ -24,8 +24,6 @@ import android.os.RemoteException; import android.text.TextUtils; import android.util.Log; import java.util.List; /** * Handles response from the {@link QuickAccessWalletService} for {@link GetWalletCardsRequest} * Loading Loading @@ -56,7 +54,6 @@ final class GetWalletCardsCallbackImpl implements GetWalletCardsCallback { * presented as the selected card. */ public void onSuccess(@NonNull GetWalletCardsResponse response) { Log.i(TAG, "onSuccess"); if (isValidResponse(response)) { mHandler.post(() -> onSuccessInternal(response)); } else { Loading @@ -78,7 +75,6 @@ final class GetWalletCardsCallbackImpl implements GetWalletCardsCallback { } private void onSuccessInternal(GetWalletCardsResponse response) { Log.i(TAG, "onSuccessInternal"); if (mCalled) { Log.w(TAG, "already called"); return; Loading @@ -86,7 +82,6 @@ final class GetWalletCardsCallbackImpl implements GetWalletCardsCallback { mCalled = true; try { mCallback.onGetWalletCardsSuccess(response); Log.i(TAG, "onSuccessInternal: returned response"); } catch (RemoteException e) { Log.w(TAG, "Error returning wallet cards", e); } Loading @@ -106,29 +101,53 @@ final class GetWalletCardsCallbackImpl implements GetWalletCardsCallback { } private boolean isValidResponse(@NonNull GetWalletCardsResponse response) { return response != null && response.getWalletCards() != null && response.getSelectedIndex() >= 0 && (response.getWalletCards().isEmpty() // selectedIndex may be 0 when list is empty || response.getSelectedIndex() < response.getWalletCards().size()) && response.getWalletCards().size() < mRequest.getMaxCards() && areValidCards(response.getWalletCards()); if (response == null) { Log.w(TAG, "Invalid response: response is null"); return false; } private boolean areValidCards(List<WalletCard> walletCards) { for (WalletCard walletCard : walletCards) { if (walletCard == null || walletCard.getCardId() == null || walletCard.getCardImage() == null || TextUtils.isEmpty(walletCard.getContentDescription()) || walletCard.getPendingIntent() == null) { if (response.getWalletCards() == null) { Log.w(TAG, "Invalid response: walletCards is null"); return false; } if (response.getSelectedIndex() < 0) { Log.w(TAG, "Invalid response: selectedIndex is negative"); return false; } if (!response.getWalletCards().isEmpty() && response.getSelectedIndex() >= response.getWalletCards().size()) { Log.w(TAG, "Invalid response: selectedIndex out of bounds"); return false; } if (response.getWalletCards().size() > mRequest.getMaxCards()) { Log.w(TAG, "Invalid response: too many cards"); return false; } for (WalletCard walletCard : response.getWalletCards()) { if (walletCard == null) { Log.w(TAG, "Invalid response: card is null"); return false; } if (walletCard.getCardId() == null) { Log.w(TAG, "Invalid response: cardId is null"); return false; } Icon cardImage = walletCard.getCardImage(); if (cardImage == null) { Log.w(TAG, "Invalid response: cardImage is null"); return false; } if (cardImage.getType() == Icon.TYPE_BITMAP && walletCard.getCardImage().getBitmap().getConfig() != Bitmap.Config.HARDWARE) { Log.w(TAG, "WalletCard bitmaps should be hardware bitmaps"); && cardImage.getBitmap().getConfig() != Bitmap.Config.HARDWARE) { Log.w(TAG, "Invalid response: cardImage bitmaps must be hardware bitmaps"); return false; } if (TextUtils.isEmpty(walletCard.getContentDescription())) { Log.w(TAG, "Invalid response: contentDescription is null"); return false; } if (walletCard.getPendingIntent() == null) { Log.w(TAG, "Invalid response: pendingIntent is null"); return false; } } return true; Loading core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java +22 −3 Original line number Diff line number Diff line Loading @@ -16,19 +16,23 @@ package android.service.quickaccesswallet; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.content.Context; import android.content.Intent; import java.io.Closeable; import java.util.concurrent.Executor; /** * Facilitates accessing cards from the {@link QuickAccessWalletService}. * * @hide */ @TestApi public interface QuickAccessWalletClient { public interface QuickAccessWalletClient extends Closeable { /** * Create a client for accessing wallet cards from the {@link QuickAccessWalletService}. If the Loading Loading @@ -91,6 +95,14 @@ public interface QuickAccessWalletClient { @NonNull GetWalletCardsRequest request, @NonNull OnWalletCardsRetrievedCallback callback); /** * Get wallet cards from the {@link QuickAccessWalletService}. */ void getWalletCards( @NonNull @CallbackExecutor Executor executor, @NonNull GetWalletCardsRequest request, @NonNull OnWalletCardsRetrievedCallback callback); /** * Callback for getWalletCards */ Loading @@ -111,12 +123,19 @@ public interface QuickAccessWalletClient { void notifyWalletDismissed(); /** * Unregister event listener. * Register an event listener. */ void addWalletServiceEventListener(@NonNull WalletServiceEventListener listener); /** * Unregister event listener * Register an event listener. */ void addWalletServiceEventListener( @NonNull @CallbackExecutor Executor executor, @NonNull WalletServiceEventListener listener); /** * Unregister an event listener */ void removeWalletServiceEventListener(@NonNull WalletServiceEventListener listener); Loading core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java +54 −52 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.service.quickaccesswallet; import static android.service.quickaccesswallet.QuickAccessWalletService.SERVICE_INTERFACE; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; Loading @@ -36,16 +37,19 @@ import android.util.Log; import com.android.internal.widget.LockPatternUtils; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Queue; import java.util.UUID; import java.util.concurrent.Executor; /** * Implements {@link QuickAccessWalletClient}. The client connects, performs requests, waits for * responses, and disconnects automatically after a short period of time. The client may * responses, and disconnects automatically one minute after the last call is performed. * * @hide */ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, ServiceConnection { Loading Loading @@ -78,15 +82,14 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser @Override public boolean isWalletServiceAvailable() { boolean available = mServiceInfo != null; Log.i(TAG, "isWalletServiceAvailable: " + available); return available; return mServiceInfo != null; } @Override public boolean isWalletFeatureAvailable() { int currentUser = ActivityManager.getCurrentUser(); return checkUserSetupComplete() return currentUser == UserHandle.USER_SYSTEM && checkUserSetupComplete() && checkSecureSetting(Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED) && !new LockPatternUtils(mContext).isUserInLockdown(currentUser); } Loading @@ -101,23 +104,29 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser public void getWalletCards( @NonNull GetWalletCardsRequest request, @NonNull OnWalletCardsRetrievedCallback callback) { getWalletCards(mContext.getMainExecutor(), request, callback); } Log.i(TAG, "getWalletCards"); @Override public void getWalletCards( @NonNull @CallbackExecutor Executor executor, @NonNull GetWalletCardsRequest request, @NonNull OnWalletCardsRetrievedCallback callback) { if (!isWalletServiceAvailable()) { callback.onWalletCardRetrievalError(new GetWalletCardsError(null, null)); executor.execute( () -> callback.onWalletCardRetrievalError(new GetWalletCardsError(null, null))); return; } BaseCallbacks serviceCallback = new BaseCallbacks() { @Override public void onGetWalletCardsSuccess(GetWalletCardsResponse response) { mHandler.post(() -> callback.onWalletCardsRetrieved(response)); executor.execute(() -> callback.onWalletCardsRetrieved(response)); } @Override public void onGetWalletCardsFailure(GetWalletCardsError error) { mHandler.post(() -> callback.onWalletCardRetrievalError(error)); executor.execute(() -> callback.onWalletCardRetrievalError(error)); } }; Loading @@ -132,11 +141,11 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser serviceCallback.onGetWalletCardsFailure(new GetWalletCardsError(null, null)); } }); } @Override public void selectWalletCard(@NonNull SelectWalletCardRequest request) { Log.i(TAG, "selectWalletCard"); if (!isWalletServiceAvailable()) { return; } Loading @@ -153,7 +162,6 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser if (!isWalletServiceAvailable()) { return; } Log.i(TAG, "notifyWalletDismissed"); executeApiCall(new ApiCaller("onWalletDismissed") { @Override public void performApiCall(IQuickAccessWalletService service) throws RemoteException { Loading @@ -164,15 +172,20 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser @Override public void addWalletServiceEventListener(WalletServiceEventListener listener) { addWalletServiceEventListener(mContext.getMainExecutor(), listener); } @Override public void addWalletServiceEventListener( @NonNull @CallbackExecutor Executor executor, @NonNull WalletServiceEventListener listener) { if (!isWalletServiceAvailable()) { return; } Log.i(TAG, "registerWalletServiceEventListener"); BaseCallbacks callback = new BaseCallbacks() { @Override public void onWalletServiceEvent(WalletServiceEvent event) { Log.i(TAG, "onWalletServiceEvent"); mHandler.post(() -> listener.onWalletServiceEvent(event)); executor.execute(() -> listener.onWalletServiceEvent(event)); } }; Loading @@ -193,7 +206,6 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser if (!isWalletServiceAvailable()) { return; } Log.i(TAG, "unregisterWalletServiceEventListener"); executeApiCall(new ApiCaller("unregisterListener") { @Override public void performApiCall(IQuickAccessWalletService service) throws RemoteException { Loading @@ -208,9 +220,13 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser }); } @Override public void close() throws IOException { disconnect(); } @Override public void disconnect() { Log.i(TAG, "disconnect"); mHandler.post(() -> disconnectInternal(true)); } Loading Loading @@ -241,18 +257,15 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser } private void connect() { Log.i(TAG, "connect"); mHandler.post(this::connectInternal); } private void connectInternal() { Log.i(TAG, "connectInternal"); if (mServiceInfo == null) { Log.w(TAG, "Wallet service unavailable"); return; } if (mIsConnected) { Log.w(TAG, "already connected"); return; } mIsConnected = true; Loading @@ -264,23 +277,14 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser } private void onConnectedInternal(IQuickAccessWalletService service) { Log.i(TAG, "onConnectedInternal"); if (!mIsConnected) { Log.w(TAG, "onConnectInternal but connection closed"); mService = null; return; } mService = service; Log.i(TAG, "onConnectedInternal success: request queue size " + mRequestQueue.size()); for (ApiCaller apiCaller : new ArrayList<>(mRequestQueue)) { try { apiCaller.performApiCall(mService); } catch (RemoteException e) { Log.e(TAG, "onConnectedInternal error", e); apiCaller.onApiError(); disconnect(); break; } performApiCallInternal(apiCaller, mService); mRequestQueue.remove(apiCaller); } } Loading @@ -290,7 +294,6 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser * posting a new delayed message. */ private void resetServiceConnectionTimeout() { Log.i(TAG, "resetServiceConnectionTimeout"); mHandler.removeMessages(MSG_TIMEOUT_SERVICE); mHandler.postDelayed( () -> disconnectInternal(true), Loading @@ -299,13 +302,11 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser } private void disconnectInternal(boolean clearEventListeners) { Log.i(TAG, "disconnectInternal: " + clearEventListeners); if (!mIsConnected) { Log.w(TAG, "already disconnected"); return; } if (clearEventListeners && !mEventListeners.isEmpty()) { Log.i(TAG, "disconnectInternal: clear event listeners"); for (WalletServiceEventListener listener : mEventListeners.keySet()) { removeWalletServiceEventListener(listener); } Loading @@ -320,27 +321,31 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser } private void executeApiCall(ApiCaller apiCaller) { Log.i(TAG, "execute: " + apiCaller.mDesc); mHandler.post(() -> executeInternal(apiCaller)); } private void executeInternal(ApiCaller apiCall) { Log.i(TAG, "executeInternal: " + apiCall.mDesc); private void executeInternal(ApiCaller apiCaller) { if (mIsConnected && mService != null) { performApiCallInternal(apiCaller, mService); } else { mRequestQueue.add(apiCaller); connect(); } } private void performApiCallInternal(ApiCaller apiCaller, IQuickAccessWalletService service) { if (service == null) { apiCaller.onApiError(); return; } try { apiCall.performApiCall(mService); Log.i(TAG, "executeInternal success: " + apiCall.mDesc); apiCaller.performApiCall(service); resetServiceConnectionTimeout(); } catch (RemoteException e) { Log.w(TAG, "executeInternal error: " + apiCall.mDesc, e); apiCall.onApiError(); Log.w(TAG, "executeInternal error: " + apiCaller.mDesc, e); apiCaller.onApiError(); disconnect(); } } else { Log.i(TAG, "executeInternal: queued" + apiCall.mDesc); mRequestQueue.add(apiCall); connect(); } } private abstract static class ApiCaller { Loading @@ -350,7 +355,8 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser this.mDesc = desc; } abstract void performApiCall(IQuickAccessWalletService service) throws RemoteException; abstract void performApiCall(IQuickAccessWalletService service) throws RemoteException; void onApiError() { Log.w(TAG, "api error: " + mDesc); Loading @@ -359,7 +365,6 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser @Override // ServiceConnection public void onServiceConnected(ComponentName name, IBinder binder) { Log.i(TAG, "onServiceConnected: " + name); IQuickAccessWalletService service = IQuickAccessWalletService.Stub.asInterface(binder); mHandler.post(() -> onConnectedInternal(service)); } Loading @@ -367,19 +372,16 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser @Override // ServiceConnection public void onServiceDisconnected(ComponentName name) { // Do not disconnect, as we may later be re-connected Log.w(TAG, "onServiceDisconnected"); } @Override // ServiceConnection public void onBindingDied(ComponentName name) { // This is a recoverable error but the client will need to reconnect. Log.w(TAG, "onBindingDied"); disconnect(); } @Override // ServiceConnection public void onNullBinding(ComponentName name) { Log.w(TAG, "onNullBinding"); disconnect(); } Loading core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java +0 −2 Original line number Diff line number Diff line Loading @@ -66,13 +66,11 @@ class QuickAccessWalletServiceInfo { static QuickAccessWalletServiceInfo tryCreate(@NonNull Context context) { ComponentName defaultPaymentApp = getDefaultPaymentApp(context); if (defaultPaymentApp == null) { Log.d(TAG, "create: default payment app not set"); return null; } ServiceInfo serviceInfo = getWalletServiceInfo(context, defaultPaymentApp.getPackageName()); if (serviceInfo == null) { Log.d(TAG, "create: unable to resolve service intent"); return null; } Loading Loading
api/test-current.txt +3 −1 Original line number Diff line number Diff line Loading @@ -3435,13 +3435,15 @@ package android.service.notification { package android.service.quickaccesswallet { public interface QuickAccessWalletClient { public interface QuickAccessWalletClient extends java.io.Closeable { method public void addWalletServiceEventListener(@NonNull android.service.quickaccesswallet.QuickAccessWalletClient.WalletServiceEventListener); method public void addWalletServiceEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.service.quickaccesswallet.QuickAccessWalletClient.WalletServiceEventListener); method @NonNull public static android.service.quickaccesswallet.QuickAccessWalletClient create(@NonNull android.content.Context); method @Nullable public android.content.Intent createWalletIntent(); method @Nullable public android.content.Intent createWalletSettingsIntent(); 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 boolean isWalletFeatureAvailable(); method public boolean isWalletFeatureAvailableWhenDeviceLocked(); method public boolean isWalletServiceAvailable(); Loading
core/java/android/service/quickaccesswallet/GetWalletCardsCallbackImpl.java +43 −24 Original line number Diff line number Diff line Loading @@ -24,8 +24,6 @@ import android.os.RemoteException; import android.text.TextUtils; import android.util.Log; import java.util.List; /** * Handles response from the {@link QuickAccessWalletService} for {@link GetWalletCardsRequest} * Loading Loading @@ -56,7 +54,6 @@ final class GetWalletCardsCallbackImpl implements GetWalletCardsCallback { * presented as the selected card. */ public void onSuccess(@NonNull GetWalletCardsResponse response) { Log.i(TAG, "onSuccess"); if (isValidResponse(response)) { mHandler.post(() -> onSuccessInternal(response)); } else { Loading @@ -78,7 +75,6 @@ final class GetWalletCardsCallbackImpl implements GetWalletCardsCallback { } private void onSuccessInternal(GetWalletCardsResponse response) { Log.i(TAG, "onSuccessInternal"); if (mCalled) { Log.w(TAG, "already called"); return; Loading @@ -86,7 +82,6 @@ final class GetWalletCardsCallbackImpl implements GetWalletCardsCallback { mCalled = true; try { mCallback.onGetWalletCardsSuccess(response); Log.i(TAG, "onSuccessInternal: returned response"); } catch (RemoteException e) { Log.w(TAG, "Error returning wallet cards", e); } Loading @@ -106,29 +101,53 @@ final class GetWalletCardsCallbackImpl implements GetWalletCardsCallback { } private boolean isValidResponse(@NonNull GetWalletCardsResponse response) { return response != null && response.getWalletCards() != null && response.getSelectedIndex() >= 0 && (response.getWalletCards().isEmpty() // selectedIndex may be 0 when list is empty || response.getSelectedIndex() < response.getWalletCards().size()) && response.getWalletCards().size() < mRequest.getMaxCards() && areValidCards(response.getWalletCards()); if (response == null) { Log.w(TAG, "Invalid response: response is null"); return false; } private boolean areValidCards(List<WalletCard> walletCards) { for (WalletCard walletCard : walletCards) { if (walletCard == null || walletCard.getCardId() == null || walletCard.getCardImage() == null || TextUtils.isEmpty(walletCard.getContentDescription()) || walletCard.getPendingIntent() == null) { if (response.getWalletCards() == null) { Log.w(TAG, "Invalid response: walletCards is null"); return false; } if (response.getSelectedIndex() < 0) { Log.w(TAG, "Invalid response: selectedIndex is negative"); return false; } if (!response.getWalletCards().isEmpty() && response.getSelectedIndex() >= response.getWalletCards().size()) { Log.w(TAG, "Invalid response: selectedIndex out of bounds"); return false; } if (response.getWalletCards().size() > mRequest.getMaxCards()) { Log.w(TAG, "Invalid response: too many cards"); return false; } for (WalletCard walletCard : response.getWalletCards()) { if (walletCard == null) { Log.w(TAG, "Invalid response: card is null"); return false; } if (walletCard.getCardId() == null) { Log.w(TAG, "Invalid response: cardId is null"); return false; } Icon cardImage = walletCard.getCardImage(); if (cardImage == null) { Log.w(TAG, "Invalid response: cardImage is null"); return false; } if (cardImage.getType() == Icon.TYPE_BITMAP && walletCard.getCardImage().getBitmap().getConfig() != Bitmap.Config.HARDWARE) { Log.w(TAG, "WalletCard bitmaps should be hardware bitmaps"); && cardImage.getBitmap().getConfig() != Bitmap.Config.HARDWARE) { Log.w(TAG, "Invalid response: cardImage bitmaps must be hardware bitmaps"); return false; } if (TextUtils.isEmpty(walletCard.getContentDescription())) { Log.w(TAG, "Invalid response: contentDescription is null"); return false; } if (walletCard.getPendingIntent() == null) { Log.w(TAG, "Invalid response: pendingIntent is null"); return false; } } return true; Loading
core/java/android/service/quickaccesswallet/QuickAccessWalletClient.java +22 −3 Original line number Diff line number Diff line Loading @@ -16,19 +16,23 @@ package android.service.quickaccesswallet; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.content.Context; import android.content.Intent; import java.io.Closeable; import java.util.concurrent.Executor; /** * Facilitates accessing cards from the {@link QuickAccessWalletService}. * * @hide */ @TestApi public interface QuickAccessWalletClient { public interface QuickAccessWalletClient extends Closeable { /** * Create a client for accessing wallet cards from the {@link QuickAccessWalletService}. If the Loading Loading @@ -91,6 +95,14 @@ public interface QuickAccessWalletClient { @NonNull GetWalletCardsRequest request, @NonNull OnWalletCardsRetrievedCallback callback); /** * Get wallet cards from the {@link QuickAccessWalletService}. */ void getWalletCards( @NonNull @CallbackExecutor Executor executor, @NonNull GetWalletCardsRequest request, @NonNull OnWalletCardsRetrievedCallback callback); /** * Callback for getWalletCards */ Loading @@ -111,12 +123,19 @@ public interface QuickAccessWalletClient { void notifyWalletDismissed(); /** * Unregister event listener. * Register an event listener. */ void addWalletServiceEventListener(@NonNull WalletServiceEventListener listener); /** * Unregister event listener * Register an event listener. */ void addWalletServiceEventListener( @NonNull @CallbackExecutor Executor executor, @NonNull WalletServiceEventListener listener); /** * Unregister an event listener */ void removeWalletServiceEventListener(@NonNull WalletServiceEventListener listener); Loading
core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java +54 −52 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.service.quickaccesswallet; import static android.service.quickaccesswallet.QuickAccessWalletService.SERVICE_INTERFACE; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; Loading @@ -36,16 +37,19 @@ import android.util.Log; import com.android.internal.widget.LockPatternUtils; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Queue; import java.util.UUID; import java.util.concurrent.Executor; /** * Implements {@link QuickAccessWalletClient}. The client connects, performs requests, waits for * responses, and disconnects automatically after a short period of time. The client may * responses, and disconnects automatically one minute after the last call is performed. * * @hide */ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, ServiceConnection { Loading Loading @@ -78,15 +82,14 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser @Override public boolean isWalletServiceAvailable() { boolean available = mServiceInfo != null; Log.i(TAG, "isWalletServiceAvailable: " + available); return available; return mServiceInfo != null; } @Override public boolean isWalletFeatureAvailable() { int currentUser = ActivityManager.getCurrentUser(); return checkUserSetupComplete() return currentUser == UserHandle.USER_SYSTEM && checkUserSetupComplete() && checkSecureSetting(Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED) && !new LockPatternUtils(mContext).isUserInLockdown(currentUser); } Loading @@ -101,23 +104,29 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser public void getWalletCards( @NonNull GetWalletCardsRequest request, @NonNull OnWalletCardsRetrievedCallback callback) { getWalletCards(mContext.getMainExecutor(), request, callback); } Log.i(TAG, "getWalletCards"); @Override public void getWalletCards( @NonNull @CallbackExecutor Executor executor, @NonNull GetWalletCardsRequest request, @NonNull OnWalletCardsRetrievedCallback callback) { if (!isWalletServiceAvailable()) { callback.onWalletCardRetrievalError(new GetWalletCardsError(null, null)); executor.execute( () -> callback.onWalletCardRetrievalError(new GetWalletCardsError(null, null))); return; } BaseCallbacks serviceCallback = new BaseCallbacks() { @Override public void onGetWalletCardsSuccess(GetWalletCardsResponse response) { mHandler.post(() -> callback.onWalletCardsRetrieved(response)); executor.execute(() -> callback.onWalletCardsRetrieved(response)); } @Override public void onGetWalletCardsFailure(GetWalletCardsError error) { mHandler.post(() -> callback.onWalletCardRetrievalError(error)); executor.execute(() -> callback.onWalletCardRetrievalError(error)); } }; Loading @@ -132,11 +141,11 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser serviceCallback.onGetWalletCardsFailure(new GetWalletCardsError(null, null)); } }); } @Override public void selectWalletCard(@NonNull SelectWalletCardRequest request) { Log.i(TAG, "selectWalletCard"); if (!isWalletServiceAvailable()) { return; } Loading @@ -153,7 +162,6 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser if (!isWalletServiceAvailable()) { return; } Log.i(TAG, "notifyWalletDismissed"); executeApiCall(new ApiCaller("onWalletDismissed") { @Override public void performApiCall(IQuickAccessWalletService service) throws RemoteException { Loading @@ -164,15 +172,20 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser @Override public void addWalletServiceEventListener(WalletServiceEventListener listener) { addWalletServiceEventListener(mContext.getMainExecutor(), listener); } @Override public void addWalletServiceEventListener( @NonNull @CallbackExecutor Executor executor, @NonNull WalletServiceEventListener listener) { if (!isWalletServiceAvailable()) { return; } Log.i(TAG, "registerWalletServiceEventListener"); BaseCallbacks callback = new BaseCallbacks() { @Override public void onWalletServiceEvent(WalletServiceEvent event) { Log.i(TAG, "onWalletServiceEvent"); mHandler.post(() -> listener.onWalletServiceEvent(event)); executor.execute(() -> listener.onWalletServiceEvent(event)); } }; Loading @@ -193,7 +206,6 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser if (!isWalletServiceAvailable()) { return; } Log.i(TAG, "unregisterWalletServiceEventListener"); executeApiCall(new ApiCaller("unregisterListener") { @Override public void performApiCall(IQuickAccessWalletService service) throws RemoteException { Loading @@ -208,9 +220,13 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser }); } @Override public void close() throws IOException { disconnect(); } @Override public void disconnect() { Log.i(TAG, "disconnect"); mHandler.post(() -> disconnectInternal(true)); } Loading Loading @@ -241,18 +257,15 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser } private void connect() { Log.i(TAG, "connect"); mHandler.post(this::connectInternal); } private void connectInternal() { Log.i(TAG, "connectInternal"); if (mServiceInfo == null) { Log.w(TAG, "Wallet service unavailable"); return; } if (mIsConnected) { Log.w(TAG, "already connected"); return; } mIsConnected = true; Loading @@ -264,23 +277,14 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser } private void onConnectedInternal(IQuickAccessWalletService service) { Log.i(TAG, "onConnectedInternal"); if (!mIsConnected) { Log.w(TAG, "onConnectInternal but connection closed"); mService = null; return; } mService = service; Log.i(TAG, "onConnectedInternal success: request queue size " + mRequestQueue.size()); for (ApiCaller apiCaller : new ArrayList<>(mRequestQueue)) { try { apiCaller.performApiCall(mService); } catch (RemoteException e) { Log.e(TAG, "onConnectedInternal error", e); apiCaller.onApiError(); disconnect(); break; } performApiCallInternal(apiCaller, mService); mRequestQueue.remove(apiCaller); } } Loading @@ -290,7 +294,6 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser * posting a new delayed message. */ private void resetServiceConnectionTimeout() { Log.i(TAG, "resetServiceConnectionTimeout"); mHandler.removeMessages(MSG_TIMEOUT_SERVICE); mHandler.postDelayed( () -> disconnectInternal(true), Loading @@ -299,13 +302,11 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser } private void disconnectInternal(boolean clearEventListeners) { Log.i(TAG, "disconnectInternal: " + clearEventListeners); if (!mIsConnected) { Log.w(TAG, "already disconnected"); return; } if (clearEventListeners && !mEventListeners.isEmpty()) { Log.i(TAG, "disconnectInternal: clear event listeners"); for (WalletServiceEventListener listener : mEventListeners.keySet()) { removeWalletServiceEventListener(listener); } Loading @@ -320,27 +321,31 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser } private void executeApiCall(ApiCaller apiCaller) { Log.i(TAG, "execute: " + apiCaller.mDesc); mHandler.post(() -> executeInternal(apiCaller)); } private void executeInternal(ApiCaller apiCall) { Log.i(TAG, "executeInternal: " + apiCall.mDesc); private void executeInternal(ApiCaller apiCaller) { if (mIsConnected && mService != null) { performApiCallInternal(apiCaller, mService); } else { mRequestQueue.add(apiCaller); connect(); } } private void performApiCallInternal(ApiCaller apiCaller, IQuickAccessWalletService service) { if (service == null) { apiCaller.onApiError(); return; } try { apiCall.performApiCall(mService); Log.i(TAG, "executeInternal success: " + apiCall.mDesc); apiCaller.performApiCall(service); resetServiceConnectionTimeout(); } catch (RemoteException e) { Log.w(TAG, "executeInternal error: " + apiCall.mDesc, e); apiCall.onApiError(); Log.w(TAG, "executeInternal error: " + apiCaller.mDesc, e); apiCaller.onApiError(); disconnect(); } } else { Log.i(TAG, "executeInternal: queued" + apiCall.mDesc); mRequestQueue.add(apiCall); connect(); } } private abstract static class ApiCaller { Loading @@ -350,7 +355,8 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser this.mDesc = desc; } abstract void performApiCall(IQuickAccessWalletService service) throws RemoteException; abstract void performApiCall(IQuickAccessWalletService service) throws RemoteException; void onApiError() { Log.w(TAG, "api error: " + mDesc); Loading @@ -359,7 +365,6 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser @Override // ServiceConnection public void onServiceConnected(ComponentName name, IBinder binder) { Log.i(TAG, "onServiceConnected: " + name); IQuickAccessWalletService service = IQuickAccessWalletService.Stub.asInterface(binder); mHandler.post(() -> onConnectedInternal(service)); } Loading @@ -367,19 +372,16 @@ public class QuickAccessWalletClientImpl implements QuickAccessWalletClient, Ser @Override // ServiceConnection public void onServiceDisconnected(ComponentName name) { // Do not disconnect, as we may later be re-connected Log.w(TAG, "onServiceDisconnected"); } @Override // ServiceConnection public void onBindingDied(ComponentName name) { // This is a recoverable error but the client will need to reconnect. Log.w(TAG, "onBindingDied"); disconnect(); } @Override // ServiceConnection public void onNullBinding(ComponentName name) { Log.w(TAG, "onNullBinding"); disconnect(); } Loading
core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java +0 −2 Original line number Diff line number Diff line Loading @@ -66,13 +66,11 @@ class QuickAccessWalletServiceInfo { static QuickAccessWalletServiceInfo tryCreate(@NonNull Context context) { ComponentName defaultPaymentApp = getDefaultPaymentApp(context); if (defaultPaymentApp == null) { Log.d(TAG, "create: default payment app not set"); return null; } ServiceInfo serviceInfo = getWalletServiceInfo(context, defaultPaymentApp.getPackageName()); if (serviceInfo == null) { Log.d(TAG, "create: unable to resolve service intent"); return null; } Loading