diff options
| author | 2021-09-23 15:50:50 -0400 | |
|---|---|---|
| committer | 2021-10-14 15:01:07 -0400 | |
| commit | 6cf7c168922d39ba10dcfb12585c5ca159e34df8 (patch) | |
| tree | afacc5c113b4e2ded4a76249a49db4faf3cd4095 | |
| parent | 3866f66fcb039a9c63b7c472f4b718994f464d0f (diff) | |
Restrict packages to a single concurrent request
A package cannot request more than one tile to be added at a given time.
They must wait until the user has responded to their last request (or
let some time pass).
Test: CTS test
Bug: 197534249
Change-Id: I7aabd522a600b026bfe0bff59391a4f78f90e78e
7 files changed, 121 insertions, 10 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt index b225f5b97d2d..5568414ef882 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -338,6 +338,7 @@ package android.app { } public class StatusBarManager { + method public void cancelRequestAddTile(@NonNull String); method public void clickNotification(@Nullable String, int, int, boolean); method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void collapsePanels(); method public void expandNotificationsPanel(); diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 64f89bc75ff6..48ceef06ea98 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -669,6 +669,21 @@ public class StatusBarManager { } } + /** + * @hide + * @param packageName + */ + @TestApi + public void cancelRequestAddTile(@NonNull String packageName) { + Objects.requireNonNull(packageName); + IStatusBarService svc = getService(); + try { + svc.cancelRequestAddTile(packageName); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + /** @hide */ public static String windowStateToString(int state) { if (state == WINDOW_STATE_HIDING) return "WINDOW_STATE_HIDING"; diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index 0f245e6821bf..4e758e6a1645 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -290,4 +290,5 @@ oneway interface IStatusBar void runGcForTest(); void requestAddTile(in ComponentName componentName, in CharSequence appName, in CharSequence label, in Icon icon, in IAddTileResultCallback callback); + void cancelRequestAddTile(in String packageName); } diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 49c32be9b43a..40a39510b50d 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -161,4 +161,5 @@ interface IStatusBarService void suppressAmbientDisplay(boolean suppress); void requestAddTile(in ComponentName componentName, in CharSequence label, in Icon icon, int userId, in IAddTileResultCallback callback); + void cancelRequestAddTile(in String packageName); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt index 3b85e5dc1ce0..210ee93bb7ef 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt @@ -55,6 +55,8 @@ class TileServiceRequestController constructor( internal const val DISMISSED = StatusBarManager.TILE_ADD_REQUEST_RESULT_DIALOG_DISMISSED } + private var dialogCanceller: ((String) -> Unit)? = null + private val commandQueueCallback = object : CommandQueue.Callbacks { override fun requestAddTile( componentName: ComponentName, @@ -67,6 +69,10 @@ class TileServiceRequestController constructor( callback.onTileRequest(it) } } + + override fun cancelRequestAddTile(packageName: String) { + dialogCanceller?.invoke(packageName) + } } fun init() { @@ -95,16 +101,21 @@ class TileServiceRequestController constructor( callback.accept(TILE_ALREADY_ADDED) return } - val dialogResponse = object : Consumer<Int> { - override fun accept(response: Int) { - if (response == ADD_TILE) { - addTile(componentName) - } - callback.accept(response) + val dialogResponse = Consumer<Int> { response -> + if (response == ADD_TILE) { + addTile(componentName) } + callback.accept(response) } val tileData = TileRequestDialog.TileData(appName, label, icon) - createDialog(tileData, dialogResponse).show() + createDialog(tileData, dialogResponse).also { dialog -> + dialogCanceller = { + if (componentName.packageName == it) { + dialog.cancel() + } + dialogCanceller = null + } + }.show() } private fun createDialog( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index f95dd346f727..c25bc84faedc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -48,6 +48,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; +import android.os.RemoteException; import android.util.Log; import android.util.Pair; import android.util.SparseArray; @@ -152,6 +153,7 @@ public class CommandQueue extends IStatusBar.Stub implements private static final int MSG_SET_NAVIGATION_BAR_LUMA_SAMPLING_ENABLED = 59 << MSG_SHIFT; private static final int MSG_SET_UDFPS_HBM_LISTENER = 60 << MSG_SHIFT; private static final int MSG_TILE_SERVICE_REQUEST_ADD = 61 << MSG_SHIFT; + private static final int MSG_TILE_SERVICE_REQUEST_CANCEL = 62 << MSG_SHIFT; public static final int FLAG_EXCLUDE_NONE = 0; public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0; @@ -416,6 +418,11 @@ public class CommandQueue extends IStatusBar.Stub implements @NonNull CharSequence label, @NonNull Icon icon, @NonNull IAddTileResultCallback callback) {} + + /** + * @see IStatusBar#cancelRequestAddTile + */ + default void cancelRequestAddTile(@NonNull String packageName) {} } public CommandQueue(Context context) { @@ -1138,6 +1145,11 @@ public class CommandQueue extends IStatusBar.Stub implements mHandler.obtainMessage(MSG_TILE_SERVICE_REQUEST_ADD, args).sendToTarget(); } + @Override + public void cancelRequestAddTile(@NonNull String s) throws RemoteException { + mHandler.obtainMessage(MSG_TILE_SERVICE_REQUEST_CANCEL, s).sendToTarget(); + } + private final class H extends Handler { private H(Looper l) { super(l); @@ -1524,6 +1536,11 @@ public class CommandQueue extends IStatusBar.Stub implements } args.recycle(); break; + case MSG_TILE_SERVICE_REQUEST_CANCEL: + String packageName = (String) msg.obj; + for (int i = 0; i < mCallbacks.size(); i++) { + mCallbacks.get(i).cancelRequestAddTile(packageName); + } } } } diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 00d01e13ec45..a0f03670793b 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -97,6 +97,7 @@ import com.android.server.wm.ActivityTaskManagerInternal; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.concurrent.TimeUnit; /** * A note on locking: We rely on the fact that calls onto mBar are oneway or @@ -142,6 +143,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D @GuardedBy("mLock") private IUdfpsHbmListener mUdfpsHbmListener; + @GuardedBy("mCurrentRequestAddTilePackages") + private final ArrayMap<String, Long> mCurrentRequestAddTilePackages = new ArrayMap<>(); + private static final long REQUEST_TIME_OUT = TimeUnit.MINUTES.toNanos(5); + private class DeathRecipient implements IBinder.DeathRecipient { public void binderDied() { mBar.asBinder().unlinkToDeath(this,0); @@ -1742,13 +1747,39 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D return; } + synchronized (mCurrentRequestAddTilePackages) { + Long lastTime = mCurrentRequestAddTilePackages.get(packageName); + final long currentTime = System.nanoTime(); + if (lastTime != null && currentTime - lastTime < REQUEST_TIME_OUT) { + try { + callback.onTileRequest( + StatusBarManager.TILE_ADD_REQUEST_ERROR_REQUEST_IN_PROGRESS); + } catch (RemoteException e) { + Slog.e(TAG, "requestAddTile", e); + } + return; + } else { + if (lastTime != null) { + cancelRequestAddTileInternal(packageName); + } + } + + mCurrentRequestAddTilePackages.put(packageName, currentTime); + } + IAddTileResultCallback proxyCallback = new IAddTileResultCallback.Stub() { @Override - public void onTileRequest(int i) throws RemoteException { + public void onTileRequest(int i) { if (i == StatusBarManager.TILE_ADD_REQUEST_RESULT_DIALOG_DISMISSED) { i = StatusBarManager.TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED; } - callback.onTileRequest(i); + if (clearTileAddRequest(packageName)) { + try { + callback.onTileRequest(i); + } catch (RemoteException e) { + Slog.e(TAG, "requestAddTile - callback", e); + } + } } }; @@ -1757,11 +1788,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D if (mBar != null) { try { mBar.requestAddTile(componentName, appName, label, icon, proxyCallback); + return; } catch (RemoteException e) { Slog.e(TAG, "requestAddTile", e); } - return; } + clearTileAddRequest(packageName); try { callback.onTileRequest(StatusBarManager.TILE_ADD_REQUEST_ERROR_NO_STATUS_BAR_SERVICE); } catch (RemoteException e) { @@ -1769,6 +1801,29 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } } + @Override + public void cancelRequestAddTile(@NonNull String packageName) { + enforceStatusBar(); + cancelRequestAddTileInternal(packageName); + } + + private void cancelRequestAddTileInternal(String packageName) { + clearTileAddRequest(packageName); + if (mBar != null) { + try { + mBar.cancelRequestAddTile(packageName); + } catch (RemoteException e) { + Slog.e(TAG, "requestAddTile", e); + } + } + } + + private boolean clearTileAddRequest(String packageName) { + synchronized (mCurrentRequestAddTilePackages) { + return mCurrentRequestAddTilePackages.remove(packageName) != null; + } + } + public String[] getStatusBarIcons() { return mContext.getResources().getStringArray(R.array.config_statusBarIcons); } @@ -1898,6 +1953,16 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } pw.println(); } + ArrayList<String> requests; + synchronized (mCurrentRequestAddTilePackages) { + requests = new ArrayList<>(mCurrentRequestAddTilePackages.keySet()); + } + pw.println(" mCurrentRequestAddTilePackages=["); + final int reqN = requests.size(); + for (int i = 0; i < reqN; i++) { + pw.println(" " + requests.get(i) + ","); + } + pw.println(" ]"); } } |