Merge "Window Z rule for closing the notification shade"
This commit is contained in:
committed by
Android (Google) Code Review
commit
ba2eb648db
@@ -40,6 +40,9 @@ public interface StatusBarManagerInternal {
|
||||
|
||||
void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
|
||||
|
||||
/** Collapses the notification shade. */
|
||||
void collapsePanels();
|
||||
|
||||
void dismissKeyboardShortcutsMenu();
|
||||
void toggleKeyboardShortcutsMenu(int deviceId);
|
||||
|
||||
|
||||
@@ -383,6 +383,16 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void collapsePanels() {
|
||||
if (mBar != null) {
|
||||
try {
|
||||
mBar.animateCollapsePanels();
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismissKeyboardShortcutsMenu() {
|
||||
if (mBar != null) {
|
||||
|
||||
@@ -118,6 +118,7 @@ import com.android.internal.protolog.common.ProtoLog;
|
||||
import com.android.server.am.PendingIntentRecord;
|
||||
import com.android.server.pm.InstantAppResolver;
|
||||
import com.android.server.power.ShutdownCheckPoints;
|
||||
import com.android.server.statusbar.StatusBarManagerInternal;
|
||||
import com.android.server.uri.NeededUriGrants;
|
||||
import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
|
||||
import com.android.server.wm.ActivityTaskSupervisor.PendingActivityLaunch;
|
||||
@@ -1589,6 +1590,20 @@ class ActivityStarter {
|
||||
newTransition.abort();
|
||||
}
|
||||
} else {
|
||||
if (!mAvoidMoveToFront && mDoResume
|
||||
&& mRootWindowContainer.hasVisibleWindowAboveNotificationShade(
|
||||
r.launchedFromUid)) {
|
||||
// If the UID launching the activity has a visible window on top of the
|
||||
// notification shade and it's launching an activity that's going to be at the
|
||||
// front, we should move the shade out of the way so the user can see it.
|
||||
// We want to avoid the case where the activity is launched on top of a
|
||||
// background task which is not moved to the front.
|
||||
StatusBarManagerInternal statusBar = mService.getStatusBarManagerInternal();
|
||||
if (statusBar != null) {
|
||||
// This results in a async call since the interface is one-way
|
||||
statusBar.collapsePanels();
|
||||
}
|
||||
}
|
||||
if (result == START_SUCCESS || result == START_TASK_TO_FRONT) {
|
||||
// The activity is started new rather than just brought forward, so record
|
||||
// it as an existence change.
|
||||
|
||||
@@ -28,6 +28,8 @@ import static android.Manifest.permission.READ_FRAME_BUFFER;
|
||||
import static android.Manifest.permission.REMOVE_TASKS;
|
||||
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
|
||||
import static android.Manifest.permission.STOP_APP_SWITCHES;
|
||||
import static android.app.ActivityManager.DROP_CLOSE_SYSTEM_DIALOGS;
|
||||
import static android.app.ActivityManager.LOCK_DOWN_CLOSE_SYSTEM_DIALOGS;
|
||||
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
|
||||
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
|
||||
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
|
||||
@@ -253,6 +255,7 @@ import com.android.server.firewall.IntentFirewall;
|
||||
import com.android.server.inputmethod.InputMethodSystemProperty;
|
||||
import com.android.server.pm.UserManagerService;
|
||||
import com.android.server.policy.PermissionPolicyInternal;
|
||||
import com.android.server.statusbar.StatusBarManagerInternal;
|
||||
import com.android.server.uri.NeededUriGrants;
|
||||
import com.android.server.uri.UriGrantsManagerInternal;
|
||||
|
||||
@@ -342,6 +345,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
/** The cached sys ui service component name from package manager. */
|
||||
private ComponentName mSysUiServiceComponent;
|
||||
private PermissionPolicyInternal mPermissionPolicyInternal;
|
||||
private StatusBarManagerInternal mStatusBarManagerInternal;
|
||||
@VisibleForTesting
|
||||
final ActivityTaskManagerInternal mInternal;
|
||||
PowerManagerInternal mPowerManagerInternal;
|
||||
@@ -2927,14 +2931,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
}
|
||||
if (!canCloseSystemDialogs(pid, uid, process)) {
|
||||
// The app can't close system dialogs, throw only if it targets S+
|
||||
if (CompatChanges.isChangeEnabled(
|
||||
ActivityManager.LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, uid)) {
|
||||
if (CompatChanges.isChangeEnabled(LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, uid)) {
|
||||
throw new SecurityException(
|
||||
"Permission Denial: " + Intent.ACTION_CLOSE_SYSTEM_DIALOGS
|
||||
+ " broadcast from " + caller + " requires "
|
||||
+ Manifest.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS + ".");
|
||||
} else if (CompatChanges.isChangeEnabled(
|
||||
ActivityManager.DROP_CLOSE_SYSTEM_DIALOGS, uid)) {
|
||||
} else if (CompatChanges.isChangeEnabled(DROP_CLOSE_SYSTEM_DIALOGS, uid)) {
|
||||
Slog.e(TAG,
|
||||
"Permission Denial: " + Intent.ACTION_CLOSE_SYSTEM_DIALOGS
|
||||
+ " broadcast from " + caller + " requires "
|
||||
@@ -2983,6 +2985,20 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// This covers the case where the app is displaying some UI on top of the notification shade
|
||||
// and wants to start an activity. The app then sends the intent in order to move the
|
||||
// notification shade out of the way and show the activity to the user. This is fine since
|
||||
// the caller already has privilege to show a visible window on top of the notification
|
||||
// shade, so it can already prevent the user from accessing the shade if it wants to.
|
||||
// We only allow for targetSdk < S, for S+ we automatically collapse the shade on
|
||||
// startActivity() for these apps.
|
||||
if (!CompatChanges.isChangeEnabled(LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, uid)) {
|
||||
synchronized (mGlobalLock) {
|
||||
if (mRootWindowContainer.hasVisibleWindowAboveNotificationShade(uid)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4787,6 +4803,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
return mPermissionPolicyInternal;
|
||||
}
|
||||
|
||||
StatusBarManagerInternal getStatusBarManagerInternal() {
|
||||
if (mStatusBarManagerInternal == null) {
|
||||
mStatusBarManagerInternal = LocalServices.getService(StatusBarManagerInternal.class);
|
||||
}
|
||||
return mStatusBarManagerInternal;
|
||||
}
|
||||
|
||||
AppWarnings getAppWarningsLocked() {
|
||||
return mAppWarnings;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import static android.view.Display.INVALID_DISPLAY;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
|
||||
import static android.view.WindowManager.TRANSIT_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
|
||||
import static android.view.WindowManager.TRANSIT_NONE;
|
||||
@@ -3137,6 +3138,27 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if {@code uid} has a visible window that's above a window of type {@link
|
||||
* WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE}. If there is no window with type {@link
|
||||
* WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE}, it returns {@code false}.
|
||||
*/
|
||||
boolean hasVisibleWindowAboveNotificationShade(int uid) {
|
||||
boolean[] visibleWindowFound = {false};
|
||||
// We only return true if we found the notification shade (ie. window of type
|
||||
// TYPE_NOTIFICATION_SHADE). Usually, it should always be there, but if for some reason
|
||||
// it isn't, we should better be on the safe side and return false for this.
|
||||
return forAllWindows(w -> {
|
||||
if (w.mOwnerUid == uid && w.isVisible()) {
|
||||
visibleWindowFound[0] = true;
|
||||
}
|
||||
if (w.mAttrs.type == TYPE_NOTIFICATION_SHADE) {
|
||||
return visibleWindowFound[0];
|
||||
}
|
||||
return false;
|
||||
}, true /* traverseTopToBottom */);
|
||||
}
|
||||
|
||||
private boolean shouldCloseAssistant(ActivityRecord r, String reason) {
|
||||
if (!r.isActivityTypeAssistant()) return false;
|
||||
if (reason == SYSTEM_DIALOG_REASON_ASSIST) return false;
|
||||
|
||||
Reference in New Issue
Block a user