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
This commit is contained in:
Fabian Kozynski
2021-09-23 15:50:50 -04:00
parent 3866f66fcb
commit 6cf7c16892
7 changed files with 121 additions and 10 deletions

View File

@@ -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();

View File

@@ -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";

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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(

View File

@@ -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);
}
}
}
}

View File

@@ -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(" ]");
}
}