Require proper permission for togglePanel()/handleSystemKey()

In S, we're preventing apps from closing notification shade unless they
fall into certain exemptions. The methods togglePanel() and
handleSystemKey() weren't properly protected, so fixing that.

These methods were @hide, only available in the AIDL and their only
usages were inside the system

Introducing @TestApis to be able to verify this in CTS.

Bug: 192946152
Test: atest -d CtsAppTestCases:android.app.cts.StatusBarManagerTest
Test: atest -d CtsLegacyNotification30TestCases:android.app.notification.legacy30.cts.StatusBarManagerApi30Test
Test: 1. adb shell input keyevent KEYCODE_SYSTEM_NAVIGATION_DOWN
      2. Verify status bar expands
      3. adb shell input keyevent KEYCODE_SYSTEM_NAVIGATION_UP
      4. Verify status bar collapses

Change-Id: I925e3570c8d275a1159e4b6912e4628c9528cb61
This commit is contained in:
Bernardo Rufino
2021-07-06 18:17:32 +01:00
parent 5fa180d64a
commit 224dd7ca0d
3 changed files with 69 additions and 16 deletions

View File

@@ -333,8 +333,10 @@ package android.app {
method public void clickNotification(@Nullable String, int, int, boolean);
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void collapsePanels();
method public void expandNotificationsPanel();
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void handleSystemKey(int);
method public void sendNotificationFeedback(@Nullable String, @Nullable android.os.Bundle);
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setExpansionDisabledForSimNetworkLock(boolean);
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void togglePanel();
}
public final class SyncNotedAppOp implements android.os.Parcelable {

View File

@@ -351,6 +351,42 @@ public class StatusBarManager {
}
}
/**
* Toggles the notification panel.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.STATUS_BAR)
@TestApi
public void togglePanel() {
try {
final IStatusBarService svc = getService();
if (svc != null) {
svc.togglePanel();
}
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
/**
* Sends system keys to the status bar.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.STATUS_BAR)
@TestApi
public void handleSystemKey(int key) {
try {
final IStatusBarService svc = getService();
if (svc != null) {
svc.handleSystemKey(key);
}
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
/**
* Expand the settings panel.
*

View File

@@ -671,20 +671,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
@Override
public void collapsePanels() {
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
if (CompatChanges.isChangeEnabled(LOCK_DOWN_COLLAPSE_STATUS_BAR, uid)) {
enforceStatusBar();
} else {
if (mContext.checkPermission(Manifest.permission.STATUS_BAR, pid, uid)
!= PackageManager.PERMISSION_GRANTED) {
enforceExpandStatusBar();
if (!mActivityTaskManager.canCloseSystemDialogs(pid, uid)) {
Slog.e(TAG, "Permission Denial: Method collapsePanels() requires permission "
+ Manifest.permission.STATUS_BAR + ", ignoring call.");
return;
}
}
if (!checkCanCollapseStatusBar("collapsePanels")) {
return;
}
if (mBar != null) {
@@ -697,7 +685,9 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
@Override
public void togglePanel() {
enforceExpandStatusBar();
if (!checkCanCollapseStatusBar("togglePanel")) {
return;
}
if (isDisable2FlagSet(DISABLE2_NOTIFICATION_SHADE)) {
return;
@@ -758,7 +748,9 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
@Override
public void handleSystemKey(int key) throws RemoteException {
enforceExpandStatusBar();
if (!checkCanCollapseStatusBar("handleSystemKey")) {
return;
}
if (mBar != null) {
try {
@@ -1201,6 +1193,29 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
"StatusBarManagerService");
}
/**
* For targetSdk S+ we require STATUS_BAR. For targetSdk < S, we only require EXPAND_STATUS_BAR
* but also require that it falls into one of the allowed use-cases to lock down abuse vector.
*/
private boolean checkCanCollapseStatusBar(String method) {
int uid = Binder.getCallingUid();
int pid = Binder.getCallingUid();
if (CompatChanges.isChangeEnabled(LOCK_DOWN_COLLAPSE_STATUS_BAR, uid)) {
enforceStatusBar();
} else {
if (mContext.checkPermission(Manifest.permission.STATUS_BAR, pid, uid)
!= PackageManager.PERMISSION_GRANTED) {
enforceExpandStatusBar();
if (!mActivityTaskManager.canCloseSystemDialogs(pid, uid)) {
Slog.e(TAG, "Permission Denial: Method " + method + "() requires permission "
+ Manifest.permission.STATUS_BAR + ", ignoring call.");
return false;
}
}
}
return true;
}
// ================================================================================
// Callbacks from the status bar service.
// ================================================================================