Merge "EventLog: Check for exception after add()" am: c30a6ac2f1
am: f8fa4b8352
Change-Id: Ia9af9320a5b73f1062f7fa0f8cd829602bce4113
diff --git a/api/system-current.txt b/api/system-current.txt
index b619c03..f25a36c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -120,6 +120,7 @@
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 8ab19c0..02a0124 100644
--- a/core/java/android/app/RemoteInput.java
+++ b/core/java/android/app/RemoteInput.java
@@ -33,8 +33,8 @@
* 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/bluetooth/BluetoothInputHost.java b/core/java/android/bluetooth/BluetoothInputHost.java
index e18d9d1..37f0427 100644
--- a/core/java/android/bluetooth/BluetoothInputHost.java
+++ b/core/java/android/bluetooth/BluetoothInputHost.java
@@ -74,7 +74,7 @@
public static final byte SUBCLASS2_GAMEPAD = (byte) 0x02;
public static final byte SUBCLASS2_REMOTE_CONTROL = (byte) 0x03;
public static final byte SUBCLASS2_SENSING_DEVICE = (byte) 0x04;
- public static final byte SUBCLASS2_DIGITIZER_TABLET = (byte) 0x05;
+ public static final byte SUBCLASS2_DIGITIZER_TABLED = (byte) 0x05;
public static final byte SUBCLASS2_CARD_READER = (byte) 0x06;
/**
diff --git a/core/java/android/os/ParcelableException.java b/core/java/android/os/ParcelableException.java
index d84d629..7f71905 100644
--- a/core/java/android/os/ParcelableException.java
+++ b/core/java/android/os/ParcelableException.java
@@ -52,10 +52,12 @@
final String msg = in.readString();
try {
final Class<?> clazz = Class.forName(name, true, Parcelable.class.getClassLoader());
- return (Throwable) clazz.getConstructor(String.class).newInstance(msg);
+ if (Throwable.class.isAssignableFrom(clazz)) {
+ return (Throwable) clazz.getConstructor(String.class).newInstance(msg);
+ }
} catch (ReflectiveOperationException e) {
- throw new RuntimeException(name + ": " + msg);
}
+ return new RuntimeException(name + ": " + msg);
}
/** {@hide} */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 06e76fe..74ad4c8 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5163,17 +5163,39 @@
public static final String ALLOW_MOCK_LOCATION = "mock_location";
/**
- * A 64-bit number (as a hex 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>
+ * 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.
*
- * <p class="note"><strong>Note:</strong> If the caller is an Instant App the id is scoped
+ * 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.
+ *
+ * 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 53b49f0..b062dc3 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -51,6 +51,7 @@
* 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 @@
* 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 @@
* 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 @@
* <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 @@
* }
* 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 @@
* 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 @@
* <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 @@
* <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 @@
*
* <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 47e8b58..590a87f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7450,7 +7450,7 @@
* {@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 @@
* {@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 @@
* <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 @@
/**
* 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 @@
* 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 d60ba16..c7f24bb 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1394,15 +1394,13 @@
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 9953c7e..9c7bfe7 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 83880e1..1b3b6a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -5241,8 +5241,7 @@
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 7e92edf..1411a54 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 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/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 0326299..36b3fbf 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -6039,12 +6039,12 @@
private int mSafeMediaVolumeIndex;
// mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
// corresponding to a gain of -30 dBFS in audio flinger mixer.
- // We remove -15 dBs from the theoretical -15dB to account for the EQ boost when bands are set
- // to max gain.
+ // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
+ // amplification when both effects are on with all band gains at maximum.
// This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
// the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
private int mSafeUsbMediaVolumeIndex;
- private static final float SAFE_VOLUME_GAIN_DBFS = -30.0f;
+ private static final float SAFE_VOLUME_GAIN_DBFS = -37.0f;
// mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET |
AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index db72c5e..e6228d4 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.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 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 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 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 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,17 @@
}
}
+ private boolean isDeviceLocked() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final KeyguardManager keyguardManager = getContext().getSystemService(
+ KeyguardManager.class);
+ return keyguardManager != null && keyguardManager.isDeviceLocked();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
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 22b0f5b..7a8c2f9 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 @@
// 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 @@
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 d7f0496..1bece69 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_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 @@
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 8ba36d5..765dc23 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 @@
*/
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 @@
}
}
+ 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 @@
}
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 @@
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 @@
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 96582fc..4d69c83 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.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_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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
&& (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 4819c0f..110d5cb 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_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 @@
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 d249b0a9..ed5cce8 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.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.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 @@
< 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 @@
return true;
} catch (SecurityException se) {
return false;
+ } catch (NameNotFoundException e) {
+ return false;
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
@@ -9657,6 +9665,13 @@
}
}
+ 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);