diff options
16 files changed, 204 insertions, 45 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index d8066f46a877..a634d41dfcc4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -120,6 +120,7 @@ package android { field public static final java.lang.String GRANT_RUNTIME_PERMISSIONS = "android.permission.GRANT_RUNTIME_PERMISSIONS"; field public static final java.lang.String HARDWARE_TEST = "android.permission.HARDWARE_TEST"; field public static final java.lang.String HDMI_CEC = "android.permission.HDMI_CEC"; + field public static final java.lang.String HIDE_NON_SYSTEM_OVERLAY_WINDOWS = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"; field public static final java.lang.String INJECT_EVENTS = "android.permission.INJECT_EVENTS"; field public static final java.lang.String INSTALL_GRANT_RUNTIME_PERMISSIONS = "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"; field public static final java.lang.String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER"; diff --git a/core/java/android/app/RemoteInput.java b/core/java/android/app/RemoteInput.java index 8ab19c06df80..02a01242c3ba 100644 --- a/core/java/android/app/RemoteInput.java +++ b/core/java/android/app/RemoteInput.java @@ -33,8 +33,8 @@ import java.util.Set; * an intent inside a {@link android.app.PendingIntent} that is sent. * Always use {@link RemoteInput.Builder} to create instances of this class. * <p class="note"> See - * <a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input from - * a Notification</a> for more information on how to use this class. + * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html#direct">Replying + * to notifications</a> for more information on how to use this class. * * <p>The following example adds a {@code RemoteInput} to a {@link Notification.Action}, * sets the result key as {@code quick_reply}, and sets the label as {@code Quick reply}. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 06e76fed6b97..74ad4c84b156 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5163,17 +5163,39 @@ public final class Settings { public static final String ALLOW_MOCK_LOCATION = "mock_location"; /** - * A 64-bit number (as a hex string) that is randomly + * On Android 8.0 (API level 26) and higher versions of the platform, + * a 64-bit number (expressed as a hexadecimal string), unique to + * each combination of app-signing key, user, and device. + * Values of {@code ANDROID_ID} are scoped by signing key and user. + * The value may change if a factory reset is performed on the + * device or if an APK signing key changes. + * + * For more information about how the platform handles {@code ANDROID_ID} + * in Android 8.0 (API level 26) and higher, see <a + * href="{@docRoot}preview/behavior-changes.html#privacy-all"> + * Android 8.0 Behavior Changes</a>. + * + * <p class="note"><strong>Note:</strong> For apps that were installed + * prior to updating the device to a version of Android 8.0 + * (API level 26) or higher, the value of {@code ANDROID_ID} changes + * if the app is uninstalled and then reinstalled after the OTA. + * To preserve values across uninstalls after an OTA to Android 8.0 + * or higher, developers can use + * <a href="{@docRoot}guide/topics/data/keyvaluebackup.html"> + * Key/Value Backup</a>.</p> + * + * <p>In versions of the platform lower than Android 8.0 (API level 26), + * a 64-bit number (expressed as a hexadecimal string) that is randomly * generated when the user first sets up the device and should remain - * constant for the lifetime of the user's device. The value may - * change if a factory reset is performed on the device. - * <p class="note"><strong>Note:</strong> When a device has <a - * href="{@docRoot}about/versions/android-4.2.html#MultipleUsers">multiple users</a> - * (available on certain devices running Android 4.2 or higher), each user appears as a - * completely separate device, so the {@code ANDROID_ID} value is unique to each - * user.</p> - * - * <p class="note"><strong>Note:</strong> If the caller is an Instant App the id is scoped + * constant for the lifetime of the user's device. + * + * On devices that have + * <a href="{@docRoot}about/versions/android-4.2.html#MultipleUsers"> + * multiple users</a>, each user appears as a + * completely separate device, so the {@code ANDROID_ID} value is + * unique to each user.</p> + * + * <p class="note"><strong>Note:</strong> If the caller is an Instant App the ID is scoped * to the Instant App, it is generated when the Instant App is first installed and reset if * the user clears the Instant App. */ diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java index 53b49f0ba373..b062dc3c18f7 100644 --- a/core/java/android/service/autofill/AutofillService.java +++ b/core/java/android/service/autofill/AutofillService.java @@ -51,6 +51,7 @@ import com.android.internal.os.SomeArgs; * Settings screen). * </ol> * + * <a name="BasicUsage"></a> * <h3>Basic usage</h3> * * <p>The basic autofill process is defined by the workflow below: @@ -122,12 +123,14 @@ import com.android.internal.os.SomeArgs; * each {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} received - if it * doesn't, the request will eventually time out and be discarded by the Android System. * + * <a name="SavingUserData"></a> * <h3>Saving user data</h3> * * <p>If the service is also interested on saving the data filled by the user, it must set a * {@link SaveInfo} object in the {@link FillResponse}. See {@link SaveInfo} for more details and * examples. * + * <a name="UserAuthentication"></a> * <h3>User authentication</h3> * * <p>The service can provide an extra degree of security by requiring the user to authenticate @@ -164,6 +167,7 @@ import com.android.internal.os.SomeArgs; * credentials in "vaults": the first response would contain fake datasets with the vault names, * and the subsequent response would contain the app credentials stored in that vault. * + * <a name="DataPartioning"></a> * <h3>Data partitioning</h3> * * <p>The autofillable views in a screen should be grouped in logical groups called "partitions". @@ -243,6 +247,7 @@ import com.android.internal.os.SomeArgs; * <p>When the service returns multiple {@link FillResponse}, the last one overrides the previous; * that's why the {@link SaveInfo} in the 2nd request above has the info for both partitions. * + * <a name="PackageVerification"></a> * <h3>Package verification</h3> * * <p>When autofilling app-specific data (like username and password), the service must verify @@ -270,9 +275,16 @@ import com.android.internal.os.SomeArgs; * } * return hash.toString(); * } - * * </pre> * + * <p>If the service did not store the signing certificates data the first time the data was saved + * — for example, because the data was created by a previous version of the app that did not + * use the Autofill Framework — the service should warn the user that the authenticity of the + * app cannot be confirmed (see an example on how to show such warning in the + * <a href="#WebSecurityDisclaimer">Web security</a> section below), and if the user agrees, + * then the service could save the data from the signing ceriticates for future use. + * + * <a name="IgnoringViews"></a> * <h3>Ignoring views</h3> * * <p>If the service find views that cannot be autofilled (for example, a text field representing @@ -281,6 +293,7 @@ import com.android.internal.os.SomeArgs; * a new {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} when these views are * focused. * + * <a name="WebSecurity"></a> * <h3>Web security</h3> * * <p>When handling autofill requests that represent web pages (typically @@ -306,16 +319,18 @@ import com.android.internal.os.SomeArgs; * <pre class="prettyprint"> * private static String getCanonicalDomain(String domain) { * InternetDomainName idn = InternetDomainName.from(domain); - * while (!idn.isTopPrivateDomain() && idn != null) { + * while (idn != null && !idn.isTopPrivateDomain()) { * idn = idn.parent(); * } * return idn == null ? null : idn.toString(); * } * </pre> * + * <a name="WebSecurityDisclaimer"></a> * <p>If the association between the web domain and app package cannot be verified through the steps - * above, the service can still autofill the app, but it should warn the user about the potential - * data leakage first, and askfor the user to confirm. For example, the service could: + * above, but the service thinks that it is appropriate to fill persisted credentials that are + * stored for the web domain, the service should warn the user about the potential data + * leakage first, and ask for the user to confirm. For example, the service could: * * <ol> * <li>Create a dataset that requires @@ -324,7 +339,7 @@ import com.android.internal.os.SomeArgs; * <li>Include the web domain in the custom presentation for the * {@link Dataset.Builder#setValue(AutofillId, AutofillValue, android.widget.RemoteViews) * dataset value}. - * <li>When the user select that dataset, show a disclaimer dialog explaining that the app is + * <li>When the user selects that dataset, show a disclaimer dialog explaining that the app is * requesting credentials for a web domain, but the service could not verify if the app owns * that domain. If the user agrees, then the service can unlock the dataset. * <li>Similarly, when adding a {@link SaveInfo} object for the request, the service should @@ -333,7 +348,7 @@ import com.android.internal.os.SomeArgs; * * <p>This same procedure could also be used when the autofillable data is contained inside an * {@code IFRAME}, in which case the WebView generates a new autofill context when a node inside - * the {@code IFRAME} is focused, which the root node containing the {@code IFRAME}'s {@code src} + * the {@code IFRAME} is focused, with the root node containing the {@code IFRAME}'s {@code src} * attribute on {@link android.app.assist.AssistStructure.ViewNode#getWebDomain()}. A typical and * legitimate use case for this scenario is a financial app that allows the user * to login on different bank accounts. For example, a financial app {@code my_financial_app} could diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 47e8b58e8e32..590a87f7337f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -7450,7 +7450,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link ViewStructure#setAutofillOptions(CharSequence[])}. * </ul> * - * <p><b>NOTE:</b> the {@code left} and {@code top} values set in + * <p><b>Note:</b> The {@code left} and {@code top} values set in * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure. * @@ -7688,6 +7688,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was * changed to the autofilled value. If not, the view will not be considered autofilled. * + * <p><b>Note:</b> After this method is called, the value returned by + * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the + * view will not be highlighted as autofilled. + * * @param value value to be autofilled. */ public void autofill(@SuppressWarnings("unused") AutofillValue value) { @@ -7711,7 +7715,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * <b>after</b> the value was changed to the autofilled value. If not, the child will not be * considered autofilled. * - * <p><b>NOTE:</b> to indicate that a virtual view was autofilled, + * <p><b>Note:</b> To indicate that a virtual view was autofilled, * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data * changes. * @@ -7780,8 +7784,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Gets the {@link View}'s current autofill value. * - * <p>By default returns {@code null}, but views should override it to properly support the - * Autofill Framework. + * <p>By default returns {@code null}, but subclasses should override it and return an + * appropriate value to properly support the Autofill Framework. * * @see #onProvideAutofillStructure(ViewStructure, int) * @see #autofill(AutofillValue) @@ -7833,7 +7837,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}. * </ol> * - * <p><b>NOTE:</strong> setting the mode as does {@link #IMPORTANT_FOR_AUTOFILL_NO} or + * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its * children) will be always be considered not important; for example, when the user explicitly * makes an autofill request, all views are considered important. See diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index d60ba16dbad6..c7f24bb0e0f1 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1394,15 +1394,13 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE = 0x00040000; /** - * Flag to indicate that this window is used as a task snapshot window. A task snapshot - * window is a starting window that gets shown with a screenshot from the previous state - * that is active until the app has drawn its first frame. - * - * <p>If this flag is set, SystemUI flags are ignored such that the real window behind can - * set the SystemUI flags. + * Flag to indicate that any window added by an application process that is of type + * {@link #TYPE_TOAST} or that requires + * {@link android.app.AppOpsManager#OP_SYSTEM_ALERT_WINDOW} permission should be hidden when + * this window is visible. * @hide */ - public static final int PRIVATE_FLAG_TASK_SNAPSHOT = 0x00080000; + public static final int PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 0x00080000; /** * Indicates that this window is the rounded corners overlay present on some diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 8f423b8a642e..cca80585a731 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2372,6 +2372,15 @@ <permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" android:protectionLevel="signature" /> + <!-- @SystemApi Allows an application to use + {@link android.view.WindowManager.LayoutsParams#PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS} + to hide non-system-overlay windows. + <p>Not for use by third-party applications. + @hide + --> + <permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS" + android:protectionLevel="signature|installer" /> + <!-- @SystemApi Allows an application to manage (create, destroy, Z-order) application tokens in the window manager. <p>Not for use by third-party applications. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 982155c8474a..fc56276bda3a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -5236,8 +5236,7 @@ public class StatusBar extends SystemUI implements DemoMode, private void maybePrepareWakeUpFromAod() { int wakefulness = mWakefulnessLifecycle.getWakefulness(); - if (mDozing && (wakefulness == WAKEFULNESS_WAKING - || wakefulness == WAKEFULNESS_ASLEEP) && !isPulsing()) { + if (mDozing && wakefulness == WAKEFULNESS_WAKING && !isPulsing()) { mScrimController.prepareWakeUpFromAod(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java index 7e92edf76b74..1411a544c346 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java @@ -154,6 +154,11 @@ public class UnlockMethodCache { public void onStrongAuthStateChanged(int userId) { update(false /* updateAlways */); } + + @Override + public void onScreenTurnedOff() { + update(false /* updateAlways */); + } }; public boolean isTrustManaged() { diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index db72c5e4cbab..efc930ebf8ea 100644 --- a/services/core/java/com/android/server/clipboard/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -20,6 +20,7 @@ import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.IActivityManager; +import android.app.KeyguardManager; import android.content.ClipData; import android.content.ClipDescription; import android.content.ContentProvider; @@ -304,7 +305,7 @@ public class ClipboardService extends SystemService { public ClipData getPrimaryClip(String pkg) { synchronized (this) { if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, pkg, - Binder.getCallingUid())) { + Binder.getCallingUid()) || isDeviceLocked()) { return null; } addActiveOwnerLocked(Binder.getCallingUid(), pkg); @@ -316,7 +317,7 @@ public class ClipboardService extends SystemService { public ClipDescription getPrimaryClipDescription(String callingPackage) { synchronized (this) { if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, - Binder.getCallingUid())) { + Binder.getCallingUid()) || isDeviceLocked()) { return null; } PerUserClipboard clipboard = getClipboard(); @@ -328,7 +329,7 @@ public class ClipboardService extends SystemService { public boolean hasPrimaryClip(String callingPackage) { synchronized (this) { if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, - Binder.getCallingUid())) { + Binder.getCallingUid()) || isDeviceLocked()) { return false; } return getClipboard().primaryClip != null; @@ -355,7 +356,7 @@ public class ClipboardService extends SystemService { public boolean hasClipboardText(String callingPackage) { synchronized (this) { if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage, - Binder.getCallingUid())) { + Binder.getCallingUid()) || isDeviceLocked()) { return false; } PerUserClipboard clipboard = getClipboard(); @@ -433,6 +434,12 @@ public class ClipboardService extends SystemService { } } + private boolean isDeviceLocked() { + final KeyguardManager keyguardManager = getContext().getSystemService( + KeyguardManager.class); + return keyguardManager != null && keyguardManager.isDeviceLocked(); + } + private final void checkUriOwnerLocked(Uri uri, int uid) { if (!"content".equals(uri.getScheme())) { return; diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 22b0f5bcdf07..7a8c2f91b4e9 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; @@ -82,6 +83,7 @@ public class Session extends IWindowSession.Stub // Set of visible alert window surfaces connected to this session. private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>(); final boolean mCanAddInternalSystemWindow; + final boolean mCanHideNonSystemOverlayWindows; private AlertWindowNotification mAlertWindowNotification; private boolean mShowingAlertWindowNotificationAllowed; private boolean mClientDead = false; @@ -99,6 +101,8 @@ public class Session extends IWindowSession.Stub mLastReportedAnimatorScale = service.getCurrentAnimatorScale(); mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission( INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED; + mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission( + HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED; mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications; StringBuilder sb = new StringBuilder(); sb.append("Session{"); diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java index d7f049621632..1bece6903eac 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java @@ -33,7 +33,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY; import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES; import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES; @@ -179,8 +178,7 @@ class TaskSnapshotSurface implements StartingSurface { layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES) | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE; - layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT - | (windowPrivateFlags & PRIVATE_FLAG_INHERITS); + layoutParams.privateFlags = windowPrivateFlags & PRIVATE_FLAG_INHERITS; layoutParams.token = token.token; layoutParams.width = LayoutParams.MATCH_PARENT; layoutParams.height = LayoutParams.MATCH_PARENT; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 8ba36d554db3..765dc23b48a0 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -498,12 +498,15 @@ public class WindowManagerService extends IWindowManager.Stub */ Runnable mWaitingForDrawnCallback; + /** List of window currently causing non-system overlay windows to be hidden. */ + private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>(); + /** * Stores for each user whether screencapture is disabled * This array is essentially a cache for all userId for * {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled} */ - SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>(); + private SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>(); IInputMethodManager mInputMethodManager; @@ -1460,6 +1463,9 @@ public class WindowManagerService extends IWindowManager.Stub } } + final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty(); + win.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows); + final AppWindowToken aToken = token.asAppWindowToken(); if (type == TYPE_APPLICATION_STARTING && aToken != null) { aToken.startingWindow = win; @@ -1733,6 +1739,7 @@ public class WindowManagerService extends IWindowManager.Stub } mPendingRemove.remove(win); mResizingWindows.remove(win); + updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */); mWindowsChanged = true; if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win); @@ -6526,6 +6533,21 @@ public class WindowManagerService extends IWindowManager.Stub ArrayList<WindowState> windows) { mRoot.dumpWindowsNoHeader(pw, dumpAll, windows); + if (!mHidingNonSystemOverlayWindows.isEmpty()) { + pw.println(); + pw.println(" Hiding System Alert Windows:"); + for (int i = mHidingNonSystemOverlayWindows.size() - 1; i >= 0; i--) { + final WindowState w = mHidingNonSystemOverlayWindows.get(i); + pw.print(" #"); pw.print(i); pw.print(' '); + pw.print(w); + if (dumpAll) { + pw.println(":"); + w.dump(pw, " ", true); + } else { + pw.println(); + } + } + } if (mPendingRemove.size() > 0) { pw.println(); pw.println(" Remove pending for:"); @@ -7650,4 +7672,28 @@ public class WindowManagerService extends IWindowManager.Stub boolean hasWideColorGamutSupport() { return mHasWideColorGamutSupport; } + + void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) { + if (!win.hideNonSystemOverlayWindowsWhenVisible()) { + return; + } + final boolean systemAlertWindowsHidden = !mHidingNonSystemOverlayWindows.isEmpty(); + if (surfaceShown) { + if (!mHidingNonSystemOverlayWindows.contains(win)) { + mHidingNonSystemOverlayWindows.add(win); + } + } else { + mHidingNonSystemOverlayWindows.remove(win); + } + + final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty(); + + if (systemAlertWindowsHidden == hideSystemAlertWindows) { + return; + } + + mRoot.forAllWindows((w) -> { + w.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows); + }, false /* traverseTopToBottom */); + } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 96582fc10058..4d69c83d7d67 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -46,6 +46,7 @@ import static android.view.WindowManager.LayoutParams.FORMAT_CHANGED; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH; @@ -59,7 +60,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; +import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED; import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM; import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME; @@ -208,6 +211,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP boolean mPolicyVisibilityAfterAnim = true; private boolean mAppOpVisibility = true; boolean mPermanentlyHidden; // the window should never be shown again + // This is a non-system overlay window that is currently force hidden. + private boolean mForceHideNonSystemOverlayWindow; boolean mAppFreezing; boolean mHidden; // Used to determine if to show child windows. boolean mWallpaperVisible; // for wallpaper, what was last vis report? @@ -2454,6 +2459,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // to handle their windows being removed from under them. return false; } + if (mForceHideNonSystemOverlayWindow) { + // This is an alert window that is currently force hidden. + return false; + } if (mPolicyVisibility && mPolicyVisibilityAfterAnim) { // Already showing. return false; @@ -2530,6 +2539,22 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return true; } + void setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide) { + if (mOwnerCanAddInternalSystemWindow + || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) { + return; + } + if (mForceHideNonSystemOverlayWindow == forceHide) { + return; + } + mForceHideNonSystemOverlayWindow = forceHide; + if (forceHide) { + hideLw(true /* doAnimation */, true /* requestAnim */); + } else { + showLw(true /* doAnimation */, true /* requestAnim */); + } + } + public void setAppOpVisibilityLw(boolean state) { if (mAppOpVisibility != state) { mAppOpVisibility = state; @@ -3424,7 +3449,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP pw.println(Integer.toHexString(mSystemUiVisibility)); } if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || !mAppOpVisibility - || isParentWindowHidden()|| mPermanentlyHidden) { + || isParentWindowHidden()|| mPermanentlyHidden || mForceHideNonSystemOverlayWindow) { pw.print(prefix); pw.print("mPolicyVisibility="); pw.print(mPolicyVisibility); pw.print(" mPolicyVisibilityAfterAnim="); @@ -3432,8 +3457,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP pw.print(" mAppOpVisibility="); pw.print(mAppOpVisibility); pw.print(" parentHidden="); pw.print(isParentWindowHidden()); - pw.print(" mPermanentlyHidden="); pw.println(mPermanentlyHidden); - } + pw.print(" mForceHideNonSystemOverlayWindow="); pw.println( + mForceHideNonSystemOverlayWindow); } if (!mRelayoutCalled || mLayoutNeeded) { pw.print(prefix); pw.print("mRelayoutCalled="); pw.print(mRelayoutCalled); pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded); @@ -3692,6 +3717,17 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0; } + /** + * Returns true if any window added by an application process that if of type + * {@link android.view.WindowManager.LayoutParams#TYPE_TOAST} or that requires that requires + * {@link android.app.AppOpsManager#OP_SYSTEM_ALERT_WINDOW} permission should be hidden when + * this window is visible. + */ + boolean hideNonSystemOverlayWindowsWhenVisible() { + return (mAttrs.privateFlags & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0 + && mSession.mCanHideNonSystemOverlayWindows; + } + /** Returns the parent window if this is a child of another window, else null. */ WindowState getParentWindow() { // NOTE: We are not calling getParent() directly as the WindowState might be a child of a diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index 4819c0f35bda..110d5cb90f45 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -24,10 +24,8 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; -import static android.view.Surface.SCALING_MODE_FREEZE; import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW; -import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; @@ -513,6 +511,8 @@ class WindowSurfaceController { void setShown(boolean surfaceShown) { mSurfaceShown = surfaceShown; + mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mAnimator.mWin, surfaceShown); + if (mWindowSession != null) { mWindowSession.onWindowSurfaceVisibilityChanged(this, mSurfaceShown, mWindowType); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index d249b0a9e1c0..ed5cce862f7f 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -99,6 +99,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; +import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.StringParceledListSlice; @@ -152,6 +153,7 @@ import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.EventLog; import android.util.Log; import android.util.Pair; import android.util.Slog; @@ -9582,6 +9584,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { < android.os.Build.VERSION_CODES.M) { return false; } + if (!isRuntimePermission(permission)) { + EventLog.writeEvent(0x534e4554, "62623498", user.getIdentifier(), ""); + return false; + } final PackageManager packageManager = mInjector.getPackageManager(); switch (grantState) { case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED: { @@ -9608,6 +9614,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return true; } catch (SecurityException se) { return false; + } catch (NameNotFoundException e) { + return false; } finally { mInjector.binderRestoreCallingIdentity(ident); } @@ -9657,6 +9665,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + public boolean isRuntimePermission(String permissionName) throws NameNotFoundException { + final PackageManager packageManager = mInjector.getPackageManager(); + PermissionInfo permissionInfo = packageManager.getPermissionInfo(permissionName, 0); + return (permissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) + == PermissionInfo.PROTECTION_DANGEROUS; + } + @Override public boolean isProvisioningAllowed(String action, String packageName) { Preconditions.checkNotNull(packageName); |