summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--api/test-current.txt6
-rw-r--r--cmds/bootanimation/Android.bp1
-rw-r--r--core/java/android/app/ActivityManager.java2
-rw-r--r--core/java/android/app/ActivityManagerInternal.java7
-rw-r--r--core/java/android/content/ContentInterface.java3
-rw-r--r--core/java/android/content/ContentProvider.java23
-rw-r--r--core/java/android/content/ContentProviderClient.java19
-rw-r--r--core/java/android/content/ContentProviderNative.java36
-rw-r--r--core/java/android/content/ContentResolver.java19
-rw-r--r--core/java/android/content/IContentProvider.java5
-rw-r--r--core/java/android/content/LoggingContentInterface.java13
-rw-r--r--core/java/android/view/IWindowSession.aidl2
-rw-r--r--core/java/android/view/WindowInfo.java15
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java4
-rw-r--r--core/java/android/view/accessibility/AccessibilityWindowInfo.java45
-rw-r--r--core/java/android/view/inputmethod/InputMethodSystemProperty.java3
-rw-r--r--core/java/com/android/internal/policy/DecorView.java9
-rw-r--r--core/res/res/values/config.xml16
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/view/WindowInfoTest.java6
-rw-r--r--core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java79
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeHost.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeUi.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java49
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java25
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java15
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java59
-rw-r--r--services/core/java/com/android/server/am/EventLogTags.logtags5
-rw-r--r--services/core/java/com/android/server/display/color/ColorDisplayService.java44
-rw-r--r--services/core/java/com/android/server/display/color/DisplayTransformManager.java26
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java24
-rw-r--r--services/core/java/com/android/server/uri/UriGrantsManagerService.java20
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java91
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java1
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java5
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java34
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java22
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java26
-rw-r--r--services/core/java/com/android/server/wm/KeyguardController.java12
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java9
-rw-r--r--services/core/java/com/android/server/wm/utils/RegionUtils.java14
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java42
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java54
-rw-r--r--services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java86
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java36
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java68
-rw-r--r--test-mock/src/android/test/mock/MockContentProvider.java13
-rw-r--r--test-mock/src/android/test/mock/MockIContentProvider.java8
-rw-r--r--tools/lock_agent/Android.bp16
62 files changed, 977 insertions, 267 deletions
diff --git a/api/current.txt b/api/current.txt
index 7c13dc1293c1..e85559601146 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -52435,6 +52435,7 @@ package android.view.accessibility {
method public int getId();
method public int getLayer();
method public android.view.accessibility.AccessibilityWindowInfo getParent();
+ method public void getRegionInScreen(@NonNull android.graphics.Region);
method public android.view.accessibility.AccessibilityNodeInfo getRoot();
method @Nullable public CharSequence getTitle();
method public int getType();
diff --git a/api/test-current.txt b/api/test-current.txt
index 050ec520059c..d2179d3f4262 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -54,6 +54,7 @@ package android.app {
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getPackageImportance(String);
method public long getTotalRam();
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidImportance(int);
+ method public static boolean isHighEndGfx();
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
method public static void resumeAppSwitches() throws android.os.RemoteException;
method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
@@ -3492,11 +3493,6 @@ package android.view.inputmethod {
method public boolean isInputMethodPickerShown();
}
- public class InputMethodSystemProperty {
- ctor public InputMethodSystemProperty();
- field public static final boolean MULTI_CLIENT_IME_ENABLED;
- }
-
}
package android.view.inspector {
diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp
index 31bd612cc2c7..c1f86544070e 100644
--- a/cmds/bootanimation/Android.bp
+++ b/cmds/bootanimation/Android.bp
@@ -79,7 +79,6 @@ cc_library_shared {
"libEGL",
"libGLESv1_CM",
"libgui",
- "libtinyalsa",
],
product_variables: {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 17368b789645..91b98c71a613 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -925,7 +925,7 @@ public class ActivityManager {
* (which tends to consume a lot more RAM).
* @hide
*/
- @UnsupportedAppUsage
+ @TestApi
static public boolean isHighEndGfx() {
return !isLowRamDeviceStatic()
&& !RoSystemProperties.CONFIG_AVOID_GFX_ACCEL
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index f8e6ae50d765..69e71185f228 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -26,6 +26,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ActivityPresentationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.UserInfo;
+import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.TransactionTooLargeException;
@@ -52,6 +53,12 @@ public abstract class ActivityManagerInternal {
*/
public abstract String checkContentProviderAccess(String authority, int userId);
+ /**
+ * Verify that calling UID has access to the given provider.
+ */
+ public abstract int checkContentProviderUriPermission(Uri uri, int userId,
+ int callingUid, int modeFlags);
+
// Called by the power manager.
public abstract void onWakefulnessChanged(int wakefulness);
diff --git a/core/java/android/content/ContentInterface.java b/core/java/android/content/ContentInterface.java
index d41d8d9cc1e2..197de9711296 100644
--- a/core/java/android/content/ContentInterface.java
+++ b/core/java/android/content/ContentInterface.java
@@ -56,6 +56,9 @@ public interface ContentInterface {
public boolean refresh(@NonNull Uri uri, @Nullable Bundle args,
@Nullable CancellationSignal cancellationSignal) throws RemoteException;
+ public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags)
+ throws RemoteException;
+
public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues)
throws RemoteException;
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 7cdd2683905f..3c799915b871 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -28,6 +28,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.app.AppOpsManager;
+import android.content.pm.PackageManager;
import android.content.pm.PathPermission;
import android.content.pm.ProviderInfo;
import android.content.res.AssetFileDescriptor;
@@ -582,6 +583,22 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
}
+ @Override
+ public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) {
+ uri = validateIncomingUri(uri);
+ uri = maybeGetUriWithoutUserId(uri);
+ Trace.traceBegin(TRACE_TAG_DATABASE, "checkUriPermission");
+ final String original = setCallingPackage(callingPkg);
+ try {
+ return mInterface.checkUriPermission(uri, uid, modeFlags);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ } finally {
+ setCallingPackage(original);
+ Trace.traceEnd(TRACE_TAG_DATABASE);
+ }
+ }
+
private void enforceFilePermission(String callingPkg, Uri uri, String mode,
IBinder callerToken) throws FileNotFoundException, SecurityException {
if (mode != null && mode.indexOf('w') != -1) {
@@ -1416,6 +1433,12 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
return false;
}
+ /** {@hide} */
+ @Override
+ public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+
/**
* @hide
* Implementation when a caller has performed an insert on the content
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 93bf5188705c..8a4330ec0ede 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -307,6 +307,25 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable {
}
}
+ /** {@hide} */
+ @Override
+ public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags)
+ throws RemoteException {
+ Preconditions.checkNotNull(uri, "uri");
+
+ beforeRemote();
+ try {
+ return mContentProvider.checkUriPermission(mPackageName, uri, uid, modeFlags);
+ } catch (DeadObjectException e) {
+ if (!mStable) {
+ mContentResolver.unstableProviderDied(mContentProvider);
+ }
+ throw e;
+ } finally {
+ afterRemote();
+ }
+ }
+
/** See {@link ContentProvider#insert ContentProvider.insert} */
@Override
public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues)
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 994833866f40..cd735d4b10a3 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -363,6 +363,19 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
reply.writeInt(out ? 0 : -1);
return true;
}
+
+ case CHECK_URI_PERMISSION_TRANSACTION: {
+ data.enforceInterface(IContentProvider.descriptor);
+ String callingPkg = data.readString();
+ Uri uri = Uri.CREATOR.createFromParcel(data);
+ int uid = data.readInt();
+ int modeFlags = data.readInt();
+
+ int out = checkUriPermission(callingPkg, uri, uid, modeFlags);
+ reply.writeNoException();
+ reply.writeInt(out);
+ return true;
+ }
}
} catch (Exception e) {
DatabaseUtils.writeExceptionToParcel(reply, e);
@@ -800,6 +813,29 @@ final class ContentProviderProxy implements IContentProvider
}
}
+ @Override
+ public int checkUriPermission(String callingPkg, Uri url, int uid, int modeFlags)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ try {
+ data.writeInterfaceToken(IContentProvider.descriptor);
+
+ data.writeString(callingPkg);
+ url.writeToParcel(data, 0);
+ data.writeInt(uid);
+ data.writeInt(modeFlags);
+
+ mRemote.transact(IContentProvider.CHECK_URI_PERMISSION_TRANSACTION, data, reply, 0);
+
+ DatabaseUtils.readExceptionFromParcel(reply);
+ return reply.readInt();
+ } finally {
+ data.recycle();
+ reply.recycle();
+ }
+ }
+
@UnsupportedAppUsage
private IBinder mRemote;
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 0a1bc85202ff..9c863591f16f 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -31,6 +31,7 @@ import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.UriGrantsManager;
+import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
@@ -1146,6 +1147,24 @@ public abstract class ContentResolver implements ContentInterface {
}
}
+ /** {@hide} */
+ @Override
+ public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) {
+ Preconditions.checkNotNull(uri, "uri");
+
+ try {
+ if (mWrapped != null) return mWrapped.checkUriPermission(uri, uid, modeFlags);
+ } catch (RemoteException e) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+
+ try (ContentProviderClient client = acquireUnstableContentProviderClient(uri)) {
+ return client.checkUriPermission(uri, uid, modeFlags);
+ } catch (RemoteException e) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+ }
+
/**
* Open a stream on to the content associated with a content URI. If there
* is no data associated with the URI, FileNotFoundException is thrown.
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 0427c2f52415..fade0ab6bb5c 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -16,6 +16,7 @@
package android.content;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
@@ -82,6 +83,9 @@ public interface IContentProvider extends IInterface {
public Bundle call(String callingPkg, String authority, String method,
@Nullable String arg, @Nullable Bundle extras) throws RemoteException;
+ public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags)
+ throws RemoteException;
+
public ICancellationSignal createCancellationSignal() throws RemoteException;
public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException;
@@ -116,4 +120,5 @@ public interface IContentProvider extends IInterface {
static final int CANONICALIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 24;
static final int UNCANONICALIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 25;
static final int REFRESH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 26;
+ static final int CHECK_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 27;
}
diff --git a/core/java/android/content/LoggingContentInterface.java b/core/java/android/content/LoggingContentInterface.java
index 83c0c9112387..1df1c4faf2fe 100644
--- a/core/java/android/content/LoggingContentInterface.java
+++ b/core/java/android/content/LoggingContentInterface.java
@@ -165,6 +165,19 @@ public class LoggingContentInterface implements ContentInterface {
}
@Override
+ public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags)
+ throws RemoteException {
+ try (Logger l = new Logger("checkUriPermission", uri, uid, modeFlags)) {
+ try {
+ return l.setResult(delegate.checkUriPermission(uri, uid, modeFlags));
+ } catch (Exception res) {
+ l.setResult(res);
+ throw res;
+ }
+ }
+ }
+
+ @Override
public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues initialValues)
throws RemoteException {
try (Logger l = new Logger("insert", uri, initialValues)) {
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 4bfd1387bef4..f73f28a943c3 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -308,7 +308,7 @@ interface IWindowSession {
/**
* Called when the system gesture exclusion has changed.
*/
- void reportSystemGestureExclusionChanged(IWindow window, in List<Rect> exclusionRects);
+ oneway void reportSystemGestureExclusionChanged(IWindow window, in List<Rect> exclusionRects);
/**
* Request the server to call setInputWindowInfo on a given Surface, and return
diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java
index abf5e3f47e45..57dfc62b4f8f 100644
--- a/core/java/android/view/WindowInfo.java
+++ b/core/java/android/view/WindowInfo.java
@@ -16,7 +16,7 @@
package android.view;
-import android.graphics.Rect;
+import android.graphics.Region;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -44,7 +44,7 @@ public class WindowInfo implements Parcelable {
public IBinder parentToken;
public IBinder activityToken;
public boolean focused;
- public final Rect boundsInScreen = new Rect();
+ public Region regionInScreen = new Region();
public List<IBinder> childTokens;
public CharSequence title;
public long accessibilityIdOfAnchor = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
@@ -73,7 +73,7 @@ public class WindowInfo implements Parcelable {
window.parentToken = other.parentToken;
window.activityToken = other.activityToken;
window.focused = other.focused;
- window.boundsInScreen.set(other.boundsInScreen);
+ window.regionInScreen.set(other.regionInScreen);
window.title = other.title;
window.accessibilityIdOfAnchor = other.accessibilityIdOfAnchor;
window.inPictureInPicture = other.inPictureInPicture;
@@ -109,7 +109,7 @@ public class WindowInfo implements Parcelable {
parcel.writeStrongBinder(parentToken);
parcel.writeStrongBinder(activityToken);
parcel.writeInt(focused ? 1 : 0);
- boundsInScreen.writeToParcel(parcel, flags);
+ regionInScreen.writeToParcel(parcel, flags);
parcel.writeCharSequence(title);
parcel.writeLong(accessibilityIdOfAnchor);
parcel.writeInt(inPictureInPicture ? 1 : 0);
@@ -132,7 +132,8 @@ public class WindowInfo implements Parcelable {
builder.append(", type=").append(type);
builder.append(", layer=").append(layer);
builder.append(", token=").append(token);
- builder.append(", bounds=").append(boundsInScreen);
+ builder.append(", region=").append(regionInScreen);
+ builder.append(", bounds=").append(regionInScreen.getBounds());
builder.append(", parent=").append(parentToken);
builder.append(", focused=").append(focused);
builder.append(", children=").append(childTokens);
@@ -151,7 +152,7 @@ public class WindowInfo implements Parcelable {
parentToken = parcel.readStrongBinder();
activityToken = parcel.readStrongBinder();
focused = (parcel.readInt() == 1);
- boundsInScreen.readFromParcel(parcel);
+ regionInScreen = Region.CREATOR.createFromParcel(parcel);
title = parcel.readCharSequence();
accessibilityIdOfAnchor = parcel.readLong();
inPictureInPicture = (parcel.readInt() == 1);
@@ -174,7 +175,7 @@ public class WindowInfo implements Parcelable {
parentToken = null;
activityToken = null;
focused = false;
- boundsInScreen.setEmpty();
+ regionInScreen.setEmpty();
if (childTokens != null) {
childTokens.clear();
}
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 985effbb9423..fd09a87aaa70 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -622,6 +622,10 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
/**
* Change type for {@link #TYPE_WINDOWS_CHANGED} event:
* The window's bounds changed.
+ * <p>
+ * Starting in {@link android.os.Build.VERSION_CODES#R R}, this event implies the window's
+ * region changed. It's also possible that region changed but bounds doesn't.
+ * </p>
*/
public static final int WINDOWS_CHANGE_BOUNDS = 0x00000008;
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index ea61ef86c1b1..6a3af3478449 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -16,9 +16,11 @@
package android.view.accessibility;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.graphics.Rect;
+import android.graphics.Region;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -107,7 +109,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
private int mBooleanProperties;
private int mId = UNDEFINED_WINDOW_ID;
private int mParentId = UNDEFINED_WINDOW_ID;
- private final Rect mBoundsInScreen = new Rect();
+ private Region mRegionInScreen = new Region();
private LongArray mChildIds;
private CharSequence mTitle;
private long mAnchorId = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
@@ -305,23 +307,33 @@ public final class AccessibilityWindowInfo implements Parcelable {
}
/**
- * Gets the bounds of this window in the screen.
+ * Gets the touchable region of this window in the screen.
*
- * @param outBounds The out window bounds.
+ * @param outRegion The out window region.
*/
- public void getBoundsInScreen(Rect outBounds) {
- outBounds.set(mBoundsInScreen);
+ public void getRegionInScreen(@NonNull Region outRegion) {
+ outRegion.set(mRegionInScreen);
}
/**
- * Sets the bounds of this window in the screen.
+ * Sets the touchable region of this window in the screen.
*
- * @param bounds The out window bounds.
+ * @param region The window region.
*
* @hide
*/
- public void setBoundsInScreen(Rect bounds) {
- mBoundsInScreen.set(bounds);
+ public void setRegionInScreen(Region region) {
+ mRegionInScreen.set(region);
+ }
+
+ /**
+ * Gets the bounds of this window in the screen. This is equivalent to get the bounds of the
+ * Region from {@link #getRegionInScreen(Region)}.
+ *
+ * @param outBounds The out window bounds.
+ */
+ public void getBoundsInScreen(Rect outBounds) {
+ outBounds.set(mRegionInScreen.getBounds());
}
/**
@@ -522,7 +534,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
parcel.writeInt(mBooleanProperties);
parcel.writeInt(mId);
parcel.writeInt(mParentId);
- mBoundsInScreen.writeToParcel(parcel, flags);
+ mRegionInScreen.writeToParcel(parcel, flags);
parcel.writeCharSequence(mTitle);
parcel.writeLong(mAnchorId);
@@ -552,7 +564,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
mBooleanProperties = other.mBooleanProperties;
mId = other.mId;
mParentId = other.mParentId;
- mBoundsInScreen.set(other.mBoundsInScreen);
+ mRegionInScreen.set(other.mRegionInScreen);
mTitle = other.mTitle;
mAnchorId = other.mAnchorId;
@@ -574,7 +586,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
mBooleanProperties = parcel.readInt();
mId = parcel.readInt();
mParentId = parcel.readInt();
- mBoundsInScreen.readFromParcel(parcel);
+ mRegionInScreen = Region.CREATOR.createFromParcel(parcel);
mTitle = parcel.readCharSequence();
mAnchorId = parcel.readLong();
@@ -621,7 +633,8 @@ public final class AccessibilityWindowInfo implements Parcelable {
builder.append(", id=").append(mId);
builder.append(", type=").append(typeToString(mType));
builder.append(", layer=").append(mLayer);
- builder.append(", bounds=").append(mBoundsInScreen);
+ builder.append(", region=").append(mRegionInScreen);
+ builder.append(", bounds=").append(mRegionInScreen.getBounds());
builder.append(", focused=").append(isFocused());
builder.append(", active=").append(isActive());
builder.append(", pictureInPicture=").append(isInPictureInPictureMode());
@@ -661,7 +674,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
mBooleanProperties = 0;
mId = UNDEFINED_WINDOW_ID;
mParentId = UNDEFINED_WINDOW_ID;
- mBoundsInScreen.setEmpty();
+ mRegionInScreen.setEmpty();
mChildIds = null;
mConnectionId = UNDEFINED_WINDOW_ID;
mAnchorId = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
@@ -716,7 +729,6 @@ public final class AccessibilityWindowInfo implements Parcelable {
}
}
-
/**
* Reports how this window differs from a possibly different state of the same window. The
* argument must have the same id and type as neither of those properties may change.
@@ -739,8 +751,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
if (!TextUtils.equals(mTitle, other.mTitle)) {
changes |= AccessibilityEvent.WINDOWS_CHANGE_TITLE;
}
-
- if (!mBoundsInScreen.equals(other.mBoundsInScreen)) {
+ if (!mRegionInScreen.equals(other.mRegionInScreen)) {
changes |= AccessibilityEvent.WINDOWS_CHANGE_BOUNDS;
}
if (mLayer != other.mLayer) {
diff --git a/core/java/android/view/inputmethod/InputMethodSystemProperty.java b/core/java/android/view/inputmethod/InputMethodSystemProperty.java
index 0689806bf832..e20c2fdc8074 100644
--- a/core/java/android/view/inputmethod/InputMethodSystemProperty.java
+++ b/core/java/android/view/inputmethod/InputMethodSystemProperty.java
@@ -17,7 +17,6 @@
package android.view.inputmethod;
import android.annotation.Nullable;
-import android.annotation.TestApi;
import android.content.ComponentName;
import android.os.Build;
import android.os.SystemProperties;
@@ -27,7 +26,6 @@ import android.os.SystemProperties;
*
* @hide
*/
-@TestApi
public class InputMethodSystemProperty {
/**
* System property key for the production use. The value must be either empty or a valid
@@ -78,6 +76,5 @@ public class InputMethodSystemProperty {
*
* @hide
*/
- @TestApi
public static final boolean MULTI_CLIENT_IME_ENABLED = (sMultiClientImeComponentName != null);
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index fe66cf9aab7d..480ff4d528f0 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -983,14 +983,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
@Override
public void setBackgroundDrawable(Drawable background) {
-
- // TODO: This should route through setWindowBackground, but late in the release to make this
- // change.
- if (mOriginalBackgroundDrawable != background) {
- mOriginalBackgroundDrawable = background;
- updateBackgroundDrawable();
- drawableChanged();
- }
+ setWindowBackground(background);
}
public void setWindowFrame(Drawable drawable) {
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5ea7f5ba578f..3b1275354d1f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1115,6 +1115,22 @@
regularly selected color mode will be used if this value is negative. -->
<integer name="config_accessibilityColorMode">-1</integer>
+ <!-- The following two arrays specify which color space to use for display composition when a
+ certain color mode is active.
+ Composition color spaces are defined in android.view.Display.COLOR_MODE_xxx, and color
+ modes are defined in ColorDisplayManager.COLOR_MODE_xxx and
+ ColorDisplayManager.VENDOR_COLOR_MODE_xxx.
+ The color space COLOR_MODE_DEFAULT (0) lets the system select the most appropriate
+ composition color space for currently displayed content. Other values (e.g.,
+ COLOR_MODE_SRGB) override system selection; these other color spaces must be supported by
+ the device for for display composition.
+ If a color mode does not have a corresponding color space specified in this array, the
+ currently set composition color space will not be modified.-->
+ <integer-array name="config_displayCompositionColorModes">
+ </integer-array>
+ <integer-array name="config_displayCompositionColorSpaces">
+ </integer-array>
+
<!-- Indicate whether to allow the device to suspend when the screen is off
due to the proximity sensor. This resource should only be set to true
if the sensor HAL correctly handles the proximity sensor as a wake-up source.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c4dbde844357..c49092effd9b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3196,6 +3196,8 @@
<java-symbol type="array" name="config_nightDisplayColorTemperatureCoefficientsNative" />
<java-symbol type="array" name="config_availableColorModes" />
<java-symbol type="integer" name="config_accessibilityColorMode" />
+ <java-symbol type="array" name="config_displayCompositionColorModes" />
+ <java-symbol type="array" name="config_displayCompositionColorSpaces" />
<java-symbol type="bool" name="config_displayWhiteBalanceAvailable" />
<java-symbol type="bool" name="config_displayWhiteBalanceEnabledDefault" />
<java-symbol type="integer" name="config_displayWhiteBalanceColorTemperatureMin" />
diff --git a/core/tests/coretests/src/android/view/WindowInfoTest.java b/core/tests/coretests/src/android/view/WindowInfoTest.java
index 037a0d9a1207..05e8bd8b6cab 100644
--- a/core/tests/coretests/src/android/view/WindowInfoTest.java
+++ b/core/tests/coretests/src/android/view/WindowInfoTest.java
@@ -91,7 +91,7 @@ public class WindowInfoTest {
assertFalse(w.focused);
assertFalse(w.inPictureInPicture);
assertFalse(w.hasFlagWatchOutsideTouch);
- assertTrue(w.boundsInScreen.isEmpty());
+ assertTrue(w.regionInScreen.isEmpty());
}
@SmallTest
@@ -114,7 +114,7 @@ public class WindowInfoTest {
equality &= w1.childTokens.equals(w2.childTokens);
equality &= w1.parentToken == w2.parentToken;
equality &= w1.activityToken == w2.activityToken;
- equality &= w1.boundsInScreen.equals(w2.boundsInScreen);
+ equality &= w1.regionInScreen.equals(w2.regionInScreen);
return equality;
}
@@ -132,6 +132,6 @@ public class WindowInfoTest {
windowInfo.focused = true;
windowInfo.inPictureInPicture = true;
windowInfo.hasFlagWatchOutsideTouch = true;
- windowInfo.boundsInScreen.set(0, 0, 1080, 1080);
+ windowInfo.regionInScreen.set(0, 0, 1080, 1080);
}
}
diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java
new file mode 100644
index 000000000000..f66717e9066c
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.policy;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+public class DecorViewTest {
+
+ private Context mContext;
+ private DecorView mDecorView;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ PhoneWindow phoneWindow = new PhoneWindow(mContext);
+ mDecorView = (DecorView) phoneWindow.getDecorView();
+ }
+
+ @Test
+ public void setBackgroundDrawableSameAsSetWindowBackground() {
+ Drawable bitmapDrawable = mContext.getResources()
+ .getDrawable(R.drawable.test16x12, mContext.getTheme());
+ int w = 16;
+ int h = 12;
+ Bitmap expectedBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+
+ mDecorView.setWindowBackground(bitmapDrawable);
+ Canvas testCanvas = new Canvas(expectedBitmap);
+ mDecorView.draw(testCanvas);
+ testCanvas.release();
+
+ Drawable expectedBackground = mDecorView.getBackground();
+
+ mDecorView.setBackgroundDrawable(bitmapDrawable);
+ Bitmap resultBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+ Canvas resCanvas = new Canvas(resultBitmap);
+ mDecorView.draw(resCanvas);
+ resCanvas.release();
+
+ // Check that the drawable is the same.
+ assertThat(mDecorView.getBackground()).isEqualTo(expectedBackground);
+ assertThat(mDecorView.getBackground()).isEqualTo(bitmapDrawable);
+
+ // Check that canvas is the same.
+ int[] expPixels = new int[w * h];
+ int[] resPixels = new int[w * h];
+ resultBitmap.getPixels(resPixels, 0, w, 0, 0, w, h);
+ expectedBitmap.getPixels(expPixels, 0, w, 0, 0, w, h);
+ assertThat(Arrays.toString(expPixels)).isEqualTo(Arrays.toString(resPixels));
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 69630c4e90e8..c7c648cd023f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -237,6 +237,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
MIN_DRAG_SIZE, getResources().getDisplayMetrics())
&& !mUpdateMonitor.isFaceDetectionRunning()) {
mUpdateMonitor.requestFaceAuth();
+ mCallback.userActivity();
showMessage(null, null);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 0e93f42a3554..d3e8b3d3236e 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -77,7 +77,7 @@ public class SysuiColorExtractor extends ColorExtractor implements Dumpable,
protected void extractWallpaperColors() {
super.extractWallpaperColors();
// mTonal is final but this method will be invoked by the base class during its ctor.
- if (mTonal == null) {
+ if (mTonal == null || mNeutralColorsLock == null) {
return;
}
mTonal.applyFallback(mLockColors == null ? mSystemColors : mLockColors, mNeutralColorsLock);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index 3c9d4a9704a0..ae6dac59b2f5 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -50,9 +50,23 @@ public interface DozeHost {
*/
void onSlpiTap(float x, float y);
+ /**
+ * Artificially dim down the the display by changing scrim opacities.
+ * @param scrimOpacity opacity from 0 to 1.
+ */
default void setAodDimmingScrim(float scrimOpacity) {}
+
+ /**
+ * Sets the actual display brightness.
+ * @param value from 0 to 255.
+ */
void setDozeScreenBrightness(int value);
+ /**
+ * Makes scrims black and changes animation durations.
+ */
+ default void prepareForGentleWakeUp() {}
+
void onIgnoreTouchWhilePulsing(boolean ignore);
/**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index 5be097c457dc..38ee2fed136d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -82,7 +82,10 @@ public class DozeScreenState implements DozeMachine.Part {
boolean messagePending = mHandler.hasCallbacks(mApplyPendingScreenState);
boolean pulseEnding = oldState == DozeMachine.State.DOZE_PULSE_DONE
&& newState == DozeMachine.State.DOZE_AOD;
- if (messagePending || oldState == DozeMachine.State.INITIALIZED || pulseEnding) {
+ boolean turningOn = (oldState == DozeMachine.State.DOZE_AOD_PAUSED
+ || oldState == DozeMachine.State.DOZE) && newState == DozeMachine.State.DOZE_AOD;
+ boolean justInitialized = oldState == DozeMachine.State.INITIALIZED;
+ if (messagePending || justInitialized || pulseEnding || turningOn) {
// During initialization, we hide the navigation bar. That is however only applied after
// a traversal; setting the screen state here is immediate however, so it can happen
// that the screen turns on again before the navigation bar is hidden. To work around
@@ -91,7 +94,7 @@ public class DozeScreenState implements DozeMachine.Part {
// Delay screen state transitions even longer while animations are running.
boolean shouldDelayTransition = newState == DozeMachine.State.DOZE_AOD
- && mParameters.shouldControlScreenOff();
+ && mParameters.shouldControlScreenOff() && !turningOn;
if (shouldDelayTransition) {
mWakeLock.setAcquired(true);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index cf04b7f192e4..6918501bfb9f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -198,7 +198,10 @@ public class DozeSensors {
updateListening();
}
- private void updateListening() {
+ /**
+ * Registers/unregisters sensors based on internal state.
+ */
+ public void updateListening() {
boolean anyListening = false;
for (TriggerSensor s : mSensors) {
// We don't want to be listening while we're PAUSED (prox sensor is covered)
@@ -231,7 +234,7 @@ public class DozeSensors {
public void onUserSwitched() {
for (TriggerSensor s : mSensors) {
- s.updateListener();
+ s.updateListening();
}
}
@@ -246,7 +249,7 @@ public class DozeSensors {
return;
}
for (TriggerSensor s : mSensors) {
- s.updateListener();
+ s.updateListening();
}
}
};
@@ -409,22 +412,22 @@ public class DozeSensors {
public void setListening(boolean listen) {
if (mRequested == listen) return;
mRequested = listen;
- updateListener();
+ updateListening();
}
public void setDisabled(boolean disabled) {
if (mDisabled == disabled) return;
mDisabled = disabled;
- updateListener();
+ updateListening();
}
public void ignoreSetting(boolean ignored) {
if (mIgnoresSetting == ignored) return;
mIgnoresSetting = ignored;
- updateListener();
+ updateListening();
}
- public void updateListener() {
+ public void updateListening() {
if (!mConfigured || mSensor == null) return;
if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)
&& !mRegistered) {
@@ -480,7 +483,7 @@ public class DozeSensors {
mCallback.onSensorPulse(mPulseReason, mSensorPerformsProxCheck, screenX, screenY,
event.values);
if (!mRegistered) {
- updateListener(); // reregister, this sensor only fires once
+ updateListening(); // reregister, this sensor only fires once
}
}));
}
@@ -541,7 +544,7 @@ public class DozeSensors {
}
@Override
- public void updateListener() {
+ public void updateListening() {
if (!mConfigured) return;
AsyncSensorManager asyncSensorManager = (AsyncSensorManager) mSensorManager;
if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 97b08d5a12a6..8ef01e8d608e 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -201,7 +201,7 @@ public class DozeTriggers implements DozeMachine.Part {
// Let's prepare the display to wake-up by drawing black.
// This will cover the hardware wake-up sequence, where the display
// becomes black for a few frames.
- mDozeHost.setAodDimmingScrim(255f);
+ mDozeHost.setAodDimmingScrim(1f);
}
mMachine.wakeUp();
}
@@ -314,6 +314,9 @@ public class DozeTriggers implements DozeMachine.Part {
break;
case DOZE_PULSE_DONE:
mDozeSensors.requestTemporaryDisable();
+ // A pulse will temporarily disable sensors that require a touch screen.
+ // Let's make sure that they are re-enabled when the pulse is over.
+ mDozeSensors.updateListening();
break;
case FINISH:
mBroadcastReceiver.unregister(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 51e96d2eecad..e877d4446c63 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -130,6 +130,7 @@ public class DozeUi implements DozeMachine.Part {
break;
case DOZE:
case DOZE_AOD_PAUSED:
+ mHost.prepareForGentleWakeUp();
unscheduleTimeTick();
break;
case DOZE_REQUEST_PULSE:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index bc7174d33b13..6a0d6e1954ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -260,6 +260,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
boolean unlockAllowed = mKeyguardBypassController.onBiometricAuthenticated(
biometricSourceType);
if (unlockAllowed) {
+ mKeyguardViewMediator.userActivity();
startWakeAndUnlock(biometricSourceType);
} else {
Log.d(TAG, "onBiometricAuthenticated aborted by bypass controller");
@@ -466,8 +467,11 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
}
if (mStatusBarKeyguardViewManager.isShowing()) {
if (mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing() && unlockingAllowed) {
- return bypass && !mKeyguardBypassController.canPlaySubtleWindowAnimations()
- ? MODE_UNLOCK_COLLAPSING : MODE_UNLOCK_FADING;
+ if (bypass && mKeyguardBypassController.canPlaySubtleWindowAnimations()) {
+ return MODE_UNLOCK_FADING;
+ } else {
+ return MODE_DISMISS_BOUNCER;
+ }
} else if (unlockingAllowed) {
return bypass ? MODE_UNLOCK_FADING : MODE_NONE;
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index 0bbfbefb7883..195870bde25a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -464,7 +464,7 @@ public class NotificationGroupManager implements OnHeadsUpChangedListener, State
if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) {
return false;
}
- if (!mHeadsUpManager.isAlerting(entry.key)) {
+ if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.key)) {
return false;
}
return (sbn.getNotification().fullScreenIntent != null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 3f38c049a977..3f4ce779123c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -487,6 +487,20 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
}
/**
+ * Set front scrim to black, cancelling animations, in order to prepare to fade them
+ * away once the display turns on.
+ */
+ public void prepareForGentleWakeUp() {
+ if (mState == ScrimState.AOD && mDozeParameters.getAlwaysOn()) {
+ mCurrentInFrontAlpha = 1f;
+ mAnimateChange = false;
+ updateScrims();
+ mAnimateChange = true;
+ mAnimationDuration = ANIMATION_DURATION_LONG;
+ }
+ }
+
+ /**
* If the lock screen sensor is active.
*/
public void setWakeLockScreenSensorActive(boolean active) {
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 40ebe583b021..e72fe3e0231e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4118,6 +4118,11 @@ public class StatusBar extends SystemUI implements DemoMode,
mScrimController.setAodFrontScrimAlpha(scrimOpacity);
}
+ @Override
+ public void prepareForGentleWakeUp() {
+ mScrimController.prepareForGentleWakeUp();
+ }
+
private void dispatchTap(View view, float x, float y) {
long now = SystemClock.elapsedRealtime();
dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_DOWN);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
index 2d6ae2629ce4..2ed0970ce44b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
@@ -24,6 +24,7 @@ import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.utils.hardware.FakeSensorManager;
import org.mockito.Answers;
import org.mockito.MockSettings;
@@ -39,6 +40,7 @@ public class DozeConfigurationUtil {
when(params.getPickupPerformsProxCheck()).thenReturn(true);
when(params.getPolicy()).thenReturn(mock(AlwaysOnDisplayPolicy.class));
when(params.doubleTapReportsTouchCoordinates()).thenReturn(false);
+ when(params.getDisplayNeedsBlanking()).thenReturn(false);
doneHolder[0] = true;
return params;
@@ -52,11 +54,17 @@ public class DozeConfigurationUtil {
when(config.pickupGestureEnabled(anyInt())).thenReturn(false);
when(config.pulseOnNotificationEnabled(anyInt())).thenReturn(true);
when(config.alwaysOnEnabled(anyInt())).thenReturn(false);
+ when(config.enabled(anyInt())).thenReturn(true);
+ when(config.getWakeLockScreenDebounce()).thenReturn(0L);
when(config.doubleTapSensorType()).thenReturn(null);
when(config.tapSensorType()).thenReturn(null);
when(config.longPressSensorType()).thenReturn(null);
+ when(config.tapGestureEnabled(anyInt())).thenReturn(true);
+ when(config.tapSensorAvailable()).thenReturn(true);
+ when(config.tapSensorType()).thenReturn(FakeSensorManager.TAP_SENSOR_TYPE);
+
when(config.dozePickupSensorAvailable()).thenReturn(false);
when(config.wakeScreenGestureAvailable()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 6979fd811817..eb8ef09d0635 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -19,6 +19,7 @@ package com.android.systemui.doze;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -27,18 +28,17 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.AlarmManager;
-import android.app.Instrumentation;
+import android.hardware.Sensor;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.Handler;
import android.os.Looper;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
-import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.dock.DockManagerFake;
+import com.android.systemui.dock.DockManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.wakelock.WakeLock;
import com.android.systemui.util.wakelock.WakeLockFake;
@@ -46,14 +46,12 @@ import com.android.systemui.utils.hardware.FakeSensorManager;
import org.junit.Before;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@SmallTest
-@Ignore("failing")
@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
+@RunWithLooper(setAsMainLooper = true)
public class DozeTriggersTest extends SysuiTestCase {
private DozeTriggers mTriggers;
private DozeMachine mMachine;
@@ -61,10 +59,10 @@ public class DozeTriggersTest extends SysuiTestCase {
private AmbientDisplayConfiguration mConfig;
private DozeParameters mParameters;
private FakeSensorManager mSensors;
+ private Sensor mTapSensor;
private WakeLock mWakeLock;
- private Instrumentation mInstrumentation;
private AlarmManager mAlarmManager;
- private DockManagerFake mDockManagerFake;
+ private DockManager mDockManagerFake;
@BeforeClass
public static void setupSuite() {
@@ -74,15 +72,15 @@ public class DozeTriggersTest extends SysuiTestCase {
@Before
public void setUp() throws Exception {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
mMachine = mock(DozeMachine.class);
mAlarmManager = mock(AlarmManager.class);
- mHost = new DozeHostFake();
+ mHost = spy(new DozeHostFake());
mConfig = DozeConfigurationUtil.createMockConfig();
mParameters = DozeConfigurationUtil.createMockParameters();
- mSensors = new FakeSensorManager(mContext);
+ mSensors = spy(new FakeSensorManager(mContext));
+ mTapSensor = mSensors.getFakeTapSensor().getSensor();
mWakeLock = new WakeLockFake();
- mDockManagerFake = spy(new DockManagerFake());
+ mDockManagerFake = mock(DockManager.class);
mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, mConfig, mParameters,
mSensors, Handler.createAsync(Looper.myLooper()), mWakeLock, true,
@@ -95,29 +93,45 @@ public class DozeTriggersTest extends SysuiTestCase {
mTriggers.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
+ clearInvocations(mMachine);
mHost.callback.onNotificationAlerted();
-
mSensors.getMockProximitySensor().sendProximityResult(false); /* Near */
verify(mMachine, never()).requestState(any());
verify(mMachine, never()).requestPulse(anyInt());
mHost.callback.onNotificationAlerted();
-
mSensors.getMockProximitySensor().sendProximityResult(true); /* Far */
verify(mMachine).requestPulse(anyInt());
}
@Test
+ public void testTransitionTo_disablesAndEnablesTouchSensors() {
+ when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
+
+ mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
+ verify(mSensors).requestTriggerSensor(any(), eq(mTapSensor));
+
+ clearInvocations(mSensors);
+ mTriggers.transitionTo(DozeMachine.State.DOZE,
+ DozeMachine.State.DOZE_REQUEST_PULSE);
+ mTriggers.transitionTo(DozeMachine.State.DOZE_REQUEST_PULSE,
+ DozeMachine.State.DOZE_PULSING);
+ verify(mSensors).cancelTriggerSensor(any(), eq(mTapSensor));
+
+ clearInvocations(mSensors);
+ mTriggers.transitionTo(DozeMachine.State.DOZE_PULSING, DozeMachine.State.DOZE_PULSE_DONE);
+ verify(mSensors).requestTriggerSensor(any(), eq(mTapSensor));
+ }
+
+ @Test
public void testDockEventListener_registerAndUnregister() {
mTriggers.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
-
verify(mDockManagerFake).addListener(any());
mTriggers.transitionTo(DozeMachine.State.DOZE, DozeMachine.State.FINISH);
-
verify(mDockManagerFake).removeListener(any());
}
@@ -128,7 +142,6 @@ public class DozeTriggersTest extends SysuiTestCase {
mTriggers.onSensor(DozeLog.REASON_SENSOR_DOUBLE_TAP,
false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */,
null /* rawValues */);
-
verify(mMachine, never()).wakeUp();
}
@@ -142,7 +155,7 @@ public class DozeTriggersTest extends SysuiTestCase {
false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */,
null /* rawValues */);
- verify(mHost).setAodDimmingScrim(eq(255));
+ verify(mHost).setAodDimmingScrim(eq(1f));
verify(mMachine).wakeUp();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index a99dc7fb6924..7d9920db36a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
@@ -192,6 +194,34 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
}
@Test
+ public void onBiometricAuthenticated_whenBypassOnBouncer_dismissBouncer() {
+ reset(mKeyguardBypassController);
+ when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+ when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
+ when(mKeyguardBypassController.onBiometricAuthenticated(any())).thenReturn(true);
+ when(mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()).thenReturn(true);
+ mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
+ BiometricSourceType.FACE);
+
+ verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
+ assertThat(mBiometricUnlockController.getMode())
+ .isEqualTo(BiometricUnlockController.MODE_DISMISS_BOUNCER);
+ }
+
+ @Test
+ public void onBiometricAuthenticated_whenBypassOnBouncer_respectsCanPlaySubtleAnim() {
+ when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+ when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
+ when(mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()).thenReturn(true);
+ mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
+ BiometricSourceType.FACE);
+
+ verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
+ assertThat(mBiometricUnlockController.getMode())
+ .isEqualTo(BiometricUnlockController.MODE_UNLOCK_FADING);
+ }
+
+ @Test
public void onBiometricAuthenticated_whenFaceAndPulsing_dontDismissKeyguard() {
reset(mUpdateMonitor);
reset(mStatusBarKeyguardViewManager);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
index a4ae166d0675..29b8ab600caf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
@@ -40,18 +40,23 @@ import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+
/**
* Rudimentary fake for SensorManager
*
- * Currently only supports the proximity sensor.
+ * Currently only supports proximity, light and tap sensors.
*
* Note that this class ignores the "Handler" argument, so the test is responsible for calling the
* listener on the right thread.
*/
public class FakeSensorManager extends SensorManager {
+ public static final String TAP_SENSOR_TYPE = "tapSensorType";
+
private final MockProximitySensor mMockProximitySensor;
private final FakeGenericSensor mFakeLightSensor;
+ private final FakeGenericSensor mFakeTapSensor;
private final FakeGenericSensor[] mSensors;
public FakeSensorManager(Context context) throws Exception {
@@ -59,12 +64,13 @@ public class FakeSensorManager extends SensorManager {
.getDefaultSensor(Sensor.TYPE_PROXIMITY);
if (proxSensor == null) {
// No prox? Let's create a fake one!
- proxSensor = createSensor(Sensor.TYPE_PROXIMITY);
+ proxSensor = createSensor(Sensor.TYPE_PROXIMITY, null);
}
mSensors = new FakeGenericSensor[]{
mMockProximitySensor = new MockProximitySensor(proxSensor),
- mFakeLightSensor = new FakeGenericSensor(createSensor(Sensor.TYPE_LIGHT)),
+ mFakeLightSensor = new FakeGenericSensor(createSensor(Sensor.TYPE_LIGHT, null)),
+ mFakeTapSensor = new FakeGenericSensor(createSensor(99, TAP_SENSOR_TYPE))
};
}
@@ -76,6 +82,10 @@ public class FakeSensorManager extends SensorManager {
return mFakeLightSensor;
}
+ public FakeGenericSensor getFakeTapSensor() {
+ return mFakeTapSensor;
+ }
+
@Override
public Sensor getDefaultSensor(int type) {
Sensor s = super.getDefaultSensor(type);
@@ -160,13 +170,13 @@ public class FakeSensorManager extends SensorManager {
@Override
protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
- return false;
+ return true;
}
@Override
protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor,
boolean disable) {
- return false;
+ return true;
}
@Override
@@ -185,12 +195,15 @@ public class FakeSensorManager extends SensorManager {
return false;
}
- private Sensor createSensor(int type) throws Exception {
+ private Sensor createSensor(int type, @Nullable String stringType) throws Exception {
Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor();
constr.setAccessible(true);
Sensor sensor = constr.newInstance();
setSensorType(sensor, type);
+ if (stringType != null) {
+ setSensorField(sensor, "mStringType", stringType);
+ }
setSensorField(sensor, "mName", "Mock " + sensor.getStringType() + "/" + type);
setSensorField(sensor, "mVendor", "Mock Vendor");
setSensorField(sensor, "mVersion", 1);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index 841527261e29..1dea2f2dd954 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -23,7 +23,6 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.graphics.Rect;
import android.graphics.Region;
import android.os.Binder;
import android.os.Handler;
@@ -277,7 +276,7 @@ public class AccessibilityWindowManager
} else if (!oldWindow.activityToken.equals(newWindow.activityToken)) {
return true;
}
- if (!oldWindow.boundsInScreen.equals(newWindow.boundsInScreen)) {
+ if (!oldWindow.regionInScreen.equals(newWindow.regionInScreen)) {
return true;
}
if (oldWindow.childTokens != null && newWindow.childTokens != null
@@ -755,20 +754,20 @@ public class AccessibilityWindowManager
boolean windowInteractiveRegionChanged = false;
final int windowCount = mWindows.size();
- final Rect currentWindowBounds = new Rect();
+ final Region currentWindowRegions = new Region();
for (int i = windowCount - 1; i >= 0; i--) {
AccessibilityWindowInfo currentWindow = mWindows.get(i);
if (windowInteractiveRegion == null) {
if (currentWindow.getId() == windowId) {
- currentWindow.getBoundsInScreen(currentWindowBounds);
- outRegion.set(currentWindowBounds);
+ currentWindow.getRegionInScreen(currentWindowRegions);
+ outRegion.set(currentWindowRegions);
windowInteractiveRegion = outRegion;
continue;
}
} else if (currentWindow.getType()
!= AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) {
- currentWindow.getBoundsInScreen(currentWindowBounds);
- if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) {
+ currentWindow.getRegionInScreen(currentWindowRegions);
+ if (windowInteractiveRegion.op(currentWindowRegions, Region.Op.DIFFERENCE)) {
windowInteractiveRegionChanged = true;
}
}
@@ -1115,7 +1114,7 @@ public class AccessibilityWindowManager
reportedWindow.setType(getTypeForWindowManagerWindowType(window.type));
reportedWindow.setLayer(window.layer);
reportedWindow.setFocused(window.focused);
- reportedWindow.setBoundsInScreen(window.boundsInScreen);
+ reportedWindow.setRegionInScreen(window.regionInScreen);
reportedWindow.setTitle(window.title);
reportedWindow.setAnchorId(window.accessibilityIdOfAnchor);
reportedWindow.setPictureInPicture(window.inPictureInPicture);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index adb0909f46b8..54fc73993323 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -392,7 +392,9 @@ import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -7706,6 +7708,34 @@ public class ActivityManagerService extends IActivityManager.Stub
return null;
}
+ int checkContentProviderUriPermission(Uri uri, int userId, int callingUid, int modeFlags) {
+ final String name = uri.getAuthority();
+ final long ident = Binder.clearCallingIdentity();
+ ContentProviderHolder holder = null;
+ try {
+ holder = getContentProviderExternalUnchecked(name, null, callingUid,
+ "*checkContentProviderUriPermission*", userId);
+ if (holder != null) {
+ return holder.provider.checkUriPermission(null, uri, callingUid, modeFlags);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Content provider dead retrieving " + uri, e);
+ return PackageManager.PERMISSION_DENIED;
+ } catch (Exception e) {
+ Log.w(TAG, "Exception while determining type of " + uri, e);
+ return PackageManager.PERMISSION_DENIED;
+ } finally {
+ try {
+ if (holder != null) {
+ removeContentProviderExternalUnchecked(name, null, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ return PackageManager.PERMISSION_DENIED;
+ }
+
private boolean canClearIdentity(int callingPid, int callingUid, int userId) {
if (UserHandle.getUserId(callingUid) == userId) {
return true;
@@ -17826,6 +17856,35 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
+ public int checkContentProviderUriPermission(Uri uri, int userId,
+ int callingUid, int modeFlags) {
+ // We can find ourselves needing to check Uri permissions while
+ // already holding the WM lock, which means reaching back here for
+ // the AM lock would cause an inversion. The WM team has requested
+ // that we use the strategy below instead of shifting where Uri
+ // grants are calculated.
+
+ // Since we could also arrive here while holding the AM lock, we
+ // can't always delegate the call through the handler, and we need
+ // to delicately dance between the deadlocks.
+ if (Thread.currentThread().holdsLock(ActivityManagerService.this)) {
+ return ActivityManagerService.this.checkContentProviderUriPermission(uri,
+ userId, callingUid, modeFlags);
+ } else {
+ final CompletableFuture<Integer> res = new CompletableFuture<>();
+ mHandler.post(() -> {
+ res.complete(ActivityManagerService.this.checkContentProviderUriPermission(uri,
+ userId, callingUid, modeFlags));
+ });
+ try {
+ return res.get();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Override
public void onWakefulnessChanged(int wakefulness) {
ActivityManagerService.this.onWakefulnessChanged(wakefulness);
}
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 421b75586224..cf0de061185f 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -146,4 +146,7 @@ option java_package com.android.server.am
30065 am_on_top_resumed_lost_called (Token|1|5),(Component Name|3),(Reason|3)
# An activity been add into stopping list
-30066 am_add_to_stopping (User|1|5),(Token|1|5),(Component Name|3),(Reason|3) \ No newline at end of file
+30066 am_add_to_stopping (User|1|5),(Token|1|5),(Component Name|3),(Reason|3)
+
+# Keyguard status changed
++30067 am_set_keyguard_shown (keyguardShowing|1),(aodShowing|1),(keyguardGoingAway|1),(Reason|3) \ No newline at end of file
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 2e5aafe0da72..7fb5b191a9b0 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -63,6 +63,8 @@ import android.provider.Settings.Secure;
import android.provider.Settings.System;
import android.util.MathUtils;
import android.util.Slog;
+import android.util.SparseIntArray;
+import android.view.Display;
import android.view.SurfaceControl;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AnimationUtils;
@@ -171,6 +173,11 @@ public final class ColorDisplayService extends SystemService {
private NightDisplayAutoMode mNightDisplayAutoMode;
+ /**
+ * Map of color modes -> display composition colorspace
+ */
+ private SparseIntArray mColorModeCompositionColorSpaces = null;
+
public ColorDisplayService(Context context) {
super(context);
mHandler = new TintHandler(DisplayThread.get().getLooper());
@@ -267,6 +274,30 @@ public final class ColorDisplayService extends SystemService {
return Secure.getIntForUser(cr, Secure.USER_SETUP_COMPLETE, 0, userHandle) == 1;
}
+ private void setUpDisplayCompositionColorSpaces(Resources res) {
+ mColorModeCompositionColorSpaces = null;
+
+ final int[] colorModes = res.getIntArray(R.array.config_displayCompositionColorModes);
+ if (colorModes == null) {
+ return;
+ }
+
+ final int[] compSpaces = res.getIntArray(R.array.config_displayCompositionColorSpaces);
+ if (compSpaces == null) {
+ return;
+ }
+
+ if (colorModes.length != compSpaces.length) {
+ Slog.e(TAG, "Number of composition color spaces doesn't match specified color modes");
+ return;
+ }
+
+ mColorModeCompositionColorSpaces = new SparseIntArray(colorModes.length);
+ for (int i = 0; i < colorModes.length; i++) {
+ mColorModeCompositionColorSpaces.put(colorModes[i], compSpaces[i]);
+ }
+ }
+
private void setUp() {
Slog.d(TAG, "setUp: currentUser=" + mCurrentUser);
@@ -359,6 +390,8 @@ public final class ColorDisplayService extends SystemService {
onAccessibilityInversionChanged();
onAccessibilityDaltonizerChanged();
+ setUpDisplayCompositionColorSpaces(getContext().getResources());
+
// Set the color mode, if valid, and immediately apply the updated tint matrix based on the
// existing activated state. This ensures consistency of tint across the color mode change.
onDisplayColorModeChanged(getColorModeInternal());
@@ -450,6 +483,14 @@ public final class ColorDisplayService extends SystemService {
}
}
+ private int getCompositionColorSpace(int mode) {
+ if (mColorModeCompositionColorSpaces == null) {
+ return Display.COLOR_MODE_INVALID;
+ }
+
+ return mColorModeCompositionColorSpaces.get(mode, Display.COLOR_MODE_INVALID);
+ }
+
private void onDisplayColorModeChanged(int mode) {
if (mode == NOT_SET) {
return;
@@ -470,7 +511,8 @@ public final class ColorDisplayService extends SystemService {
// DisplayTransformManager.needsLinearColorMatrix(), therefore it is dependent
// on the state of DisplayTransformManager.
final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
- dtm.setColorMode(mode, mNightDisplayTintController.getMatrix());
+ dtm.setColorMode(mode, mNightDisplayTintController.getMatrix(),
+ getCompositionColorSpace(mode));
if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) {
updateDisplayWhiteBalanceStatus();
diff --git a/services/core/java/com/android/server/display/color/DisplayTransformManager.java b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
index 5ff45a97706e..d5706a59b987 100644
--- a/services/core/java/com/android/server/display/color/DisplayTransformManager.java
+++ b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
@@ -26,6 +26,7 @@ import android.os.ServiceManager;
import android.os.SystemProperties;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -77,6 +78,8 @@ public class DisplayTransformManager {
@VisibleForTesting
static final String PERSISTENT_PROPERTY_SATURATION = "persist.sys.sf.color_saturation";
@VisibleForTesting
+ static final String PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE = "persist.sys.sf.color_mode";
+ @VisibleForTesting
static final String PERSISTENT_PROPERTY_DISPLAY_COLOR = "persist.sys.sf.native_mode";
private static final float COLOR_SATURATION_NATURAL = 1.0f;
@@ -251,23 +254,24 @@ public class DisplayTransformManager {
/**
* Sets color mode and updates night display transform values.
*/
- public boolean setColorMode(int colorMode, float[] nightDisplayMatrix) {
+ public boolean setColorMode(int colorMode, float[] nightDisplayMatrix,
+ int compositionColorMode) {
if (colorMode == ColorDisplayManager.COLOR_MODE_NATURAL) {
applySaturation(COLOR_SATURATION_NATURAL);
- setDisplayColor(DISPLAY_COLOR_MANAGED);
+ setDisplayColor(DISPLAY_COLOR_MANAGED, compositionColorMode);
} else if (colorMode == ColorDisplayManager.COLOR_MODE_BOOSTED) {
applySaturation(COLOR_SATURATION_BOOSTED);
- setDisplayColor(DISPLAY_COLOR_MANAGED);
+ setDisplayColor(DISPLAY_COLOR_MANAGED, compositionColorMode);
} else if (colorMode == ColorDisplayManager.COLOR_MODE_SATURATED) {
applySaturation(COLOR_SATURATION_NATURAL);
- setDisplayColor(DISPLAY_COLOR_UNMANAGED);
+ setDisplayColor(DISPLAY_COLOR_UNMANAGED, compositionColorMode);
} else if (colorMode == ColorDisplayManager.COLOR_MODE_AUTOMATIC) {
applySaturation(COLOR_SATURATION_NATURAL);
- setDisplayColor(DISPLAY_COLOR_ENHANCED);
+ setDisplayColor(DISPLAY_COLOR_ENHANCED, compositionColorMode);
} else if (colorMode >= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MIN
&& colorMode <= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MAX) {
applySaturation(COLOR_SATURATION_NATURAL);
- setDisplayColor(colorMode);
+ setDisplayColor(colorMode, compositionColorMode);
}
setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, nightDisplayMatrix);
@@ -323,13 +327,21 @@ public class DisplayTransformManager {
/**
* Toggles native mode on/off in SurfaceFlinger.
*/
- private void setDisplayColor(int color) {
+ private void setDisplayColor(int color, int compositionColorMode) {
SystemProperties.set(PERSISTENT_PROPERTY_DISPLAY_COLOR, Integer.toString(color));
+ if (compositionColorMode != Display.COLOR_MODE_INVALID) {
+ SystemProperties.set(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE,
+ Integer.toString(compositionColorMode));
+ }
+
final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER);
if (flinger != null) {
final Parcel data = Parcel.obtain();
data.writeInterfaceToken("android.ui.ISurfaceComposer");
data.writeInt(color);
+ if (compositionColorMode != Display.COLOR_MODE_INVALID) {
+ data.writeInt(compositionColorMode);
+ }
try {
flinger.transact(SURFACE_FLINGER_TRANSACTION_DISPLAY_COLOR, data, null, 0);
} catch (RemoteException ex) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 07fd3228dec2..d30895efbdc3 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -401,7 +401,7 @@ public class NotificationManagerService extends SystemService {
// for enabling and disabling notification pulse behavior
boolean mScreenOn = true;
- protected boolean mInCall = false;
+ protected boolean mInCallStateOffHook = false;
boolean mNotificationPulseEnabled;
private Uri mInCallNotificationUri;
@@ -1299,7 +1299,7 @@ public class NotificationManagerService extends SystemService {
mScreenOn = false;
updateNotificationPulse();
} else if (action.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
- mInCall = TelephonyManager.EXTRA_STATE_OFFHOOK
+ mInCallStateOffHook = TelephonyManager.EXTRA_STATE_OFFHOOK
.equals(intent.getStringExtra(TelephonyManager.EXTRA_STATE));
updateNotificationPulse();
} else if (action.equals(Intent.ACTION_USER_STOPPED)) {
@@ -5824,7 +5824,7 @@ public class NotificationManagerService extends SystemService {
}
if (DBG) Slog.v(TAG, "Interrupting!");
if (hasValidSound) {
- if (mInCall) {
+ if (isInCall()) {
playInCallNotification();
beep = true;
} else {
@@ -5838,7 +5838,7 @@ public class NotificationManagerService extends SystemService {
final boolean ringerModeSilent =
mAudioManager.getRingerModeInternal()
== AudioManager.RINGER_MODE_SILENT;
- if (!mInCall && hasValidVibrate && !ringerModeSilent) {
+ if (!isInCall() && hasValidVibrate && !ringerModeSilent) {
buzz = playVibration(record, vibration, hasValidSound);
if(buzz) {
mVibrateNotificationKey = key;
@@ -5926,7 +5926,7 @@ public class NotificationManagerService extends SystemService {
return false;
}
// not if in call or the screen's on
- if (mInCall || mScreenOn) {
+ if (isInCall() || mScreenOn) {
return false;
}
@@ -7027,7 +7027,7 @@ public class NotificationManagerService extends SystemService {
}
// Don't flash while we are in a call or screen is on
- if (ledNotification == null || mInCall || mScreenOn) {
+ if (ledNotification == null || isInCall() || mScreenOn) {
mNotificationLight.turnOff();
} else {
NotificationRecord.Light light = ledNotification.getLight();
@@ -7495,6 +7495,18 @@ public class NotificationManagerService extends SystemService {
}
}
+ private boolean isInCall() {
+ if (mInCallStateOffHook) {
+ return true;
+ }
+ int audioMode = mAudioManager.getMode();
+ if (audioMode == AudioManager.MODE_IN_CALL
+ || audioMode == AudioManager.MODE_IN_COMMUNICATION) {
+ return true;
+ }
+ return false;
+ }
+
public class NotificationAssistants extends ManagedServices {
static final String TAG_ENABLED_NOTIFICATION_ASSISTANTS = "enabled_assistants";
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 55f062bca2d1..b2f115374305 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -949,7 +949,25 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
return false;
}
- return readMet && writeMet;
+ // If this provider says that grants are always required, we need to
+ // consult it directly to determine if the UID has permission
+ final boolean forceMet;
+ if (pi.forceUriPermissions) {
+ final int providerUserId = UserHandle.getUserId(pi.applicationInfo.uid);
+ final int clientUserId = UserHandle.getUserId(uid);
+ if (providerUserId == clientUserId) {
+ forceMet = (mAmInternal.checkContentProviderUriPermission(grantUri.uri,
+ providerUserId, uid, modeFlags) == PackageManager.PERMISSION_GRANTED);
+ } else {
+ // The provider can't track cross-user permissions, so we have
+ // to assume they're always denied
+ forceMet = false;
+ }
+ } else {
+ forceMet = true;
+ }
+
+ return readMet && writeMet && forceMet;
}
private void removeUriPermissionIfNeeded(UriPermission perm) {
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index bace7e3c6dab..8abfde2c5c36 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.utils.RegionUtils.forEachRect;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
@@ -1126,14 +1127,13 @@ final class AccessibilityController {
// Iterate until we figure out what is touchable for the entire screen.
for (int i = visibleWindowCount - 1; i >= 0; i--) {
final WindowState windowState = visibleWindows.valueAt(i);
+ final Region regionInScreen = new Region();
+ computeWindowRegionInScreen(windowState, regionInScreen);
- final Rect boundsInScreen = mTempRect;
- computeWindowBoundsInScreen(windowState, boundsInScreen);
-
- if (windowMattersToAccessibility(windowState, boundsInScreen, unaccountedSpace,
+ if (windowMattersToAccessibility(windowState, regionInScreen, unaccountedSpace,
skipRemainingWindowsForTasks)) {
- addPopulatedWindowInfo(windowState, boundsInScreen, windows, addedWindows);
- updateUnaccountedSpace(windowState, boundsInScreen, unaccountedSpace,
+ addPopulatedWindowInfo(windowState, regionInScreen, windows, addedWindows);
+ updateUnaccountedSpace(windowState, regionInScreen, unaccountedSpace,
skipRemainingWindowsForTasks);
focusedWindowAdded |= windowState.isFocused();
}
@@ -1171,8 +1171,9 @@ final class AccessibilityController {
clearAndRecycleWindows(windows);
}
- private boolean windowMattersToAccessibility(WindowState windowState, Rect boundsInScreen,
- Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) {
+ private boolean windowMattersToAccessibility(WindowState windowState,
+ Region regionInScreen, Region unaccountedSpace,
+ HashSet<Integer> skipRemainingWindowsForTasks) {
if (windowState.isFocused()) {
return true;
}
@@ -1192,7 +1193,7 @@ final class AccessibilityController {
}
// If the window is completely covered by other windows - ignore.
- if (unaccountedSpace.quickReject(boundsInScreen)) {
+ if (unaccountedSpace.quickReject(regionInScreen)) {
return false;
}
@@ -1204,7 +1205,7 @@ final class AccessibilityController {
return false;
}
- private void updateUnaccountedSpace(WindowState windowState, Rect boundsInScreen,
+ private void updateUnaccountedSpace(WindowState windowState, Region regionInScreen,
Region unaccountedSpace, HashSet<Integer> skipRemainingWindowsForTasks) {
if (windowState.mAttrs.type
!= WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
@@ -1212,59 +1213,71 @@ final class AccessibilityController {
// Account for the space this window takes if the window
// is not an accessibility overlay which does not change
// the reported windows.
- unaccountedSpace.op(boundsInScreen, unaccountedSpace,
+ unaccountedSpace.op(regionInScreen, unaccountedSpace,
Region.Op.REVERSE_DIFFERENCE);
// If a window is modal it prevents other windows from being touched
if ((windowState.mAttrs.flags & (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)) == 0) {
- // Account for all space in the task, whether the windows in it are
- // touchable or not. The modal window blocks all touches from the task's
- // area.
- unaccountedSpace.op(windowState.getDisplayFrameLw(), unaccountedSpace,
- Region.Op.REVERSE_DIFFERENCE);
+ if (!windowState.hasTapExcludeRegion()) {
+ // Account for all space in the task, whether the windows in it are
+ // touchable or not. The modal window blocks all touches from the task's
+ // area.
+ unaccountedSpace.op(windowState.getDisplayFrameLw(), unaccountedSpace,
+ Region.Op.REVERSE_DIFFERENCE);
+ } else {
+ // If a window has tap exclude region, we need to account it.
+ final Region displayRegion = new Region(windowState.getDisplayFrameLw());
+ final Region tapExcludeRegion = new Region();
+ windowState.amendTapExcludeRegion(tapExcludeRegion);
+ displayRegion.op(tapExcludeRegion, displayRegion,
+ Region.Op.REVERSE_DIFFERENCE);
+ unaccountedSpace.op(displayRegion, unaccountedSpace,
+ Region.Op.REVERSE_DIFFERENCE);
+ }
final Task task = windowState.getTask();
if (task != null) {
// If the window is associated with a particular task, we can skip the
// rest of the windows for that task.
skipRemainingWindowsForTasks.add(task.mTaskId);
- } else {
+ } else if (!windowState.hasTapExcludeRegion()) {
// If the window is not associated with a particular task, then it is
- // globally modal. In this case we can skip all remaining windows.
+ // globally modal. In this case we can skip all remaining windows when
+ // it doesn't has tap exclude region.
unaccountedSpace.setEmpty();
}
}
}
}
- private void computeWindowBoundsInScreen(WindowState windowState, Rect outBounds) {
+ private void computeWindowRegionInScreen(WindowState windowState, Region outRegion) {
// Get the touchable frame.
Region touchableRegion = mTempRegion1;
windowState.getTouchableRegion(touchableRegion);
- Rect touchableFrame = mTempRect;
- touchableRegion.getBounds(touchableFrame);
-
- // Move to origin as all transforms are captured by the matrix.
- RectF windowFrame = mTempRectF;
- windowFrame.set(touchableFrame);
- windowFrame.offset(-windowState.getFrameLw().left, -windowState.getFrameLw().top);
// Map the frame to get what appears on the screen.
Matrix matrix = mTempMatrix;
populateTransformationMatrixLocked(windowState, matrix);
- matrix.mapRect(windowFrame);
- // Got the bounds.
- outBounds.set((int) windowFrame.left, (int) windowFrame.top,
- (int) windowFrame.right, (int) windowFrame.bottom);
+ forEachRect(touchableRegion, rect -> {
+ // Move to origin as all transforms are captured by the matrix.
+ RectF windowFrame = mTempRectF;
+ windowFrame.set(rect);
+ windowFrame.offset(-windowState.getFrameLw().left, -windowState.getFrameLw().top);
+
+ matrix.mapRect(windowFrame);
+
+ // Union all rects.
+ outRegion.union(new Rect((int) windowFrame.left, (int) windowFrame.top,
+ (int) windowFrame.right, (int) windowFrame.bottom));
+ });
}
- private static void addPopulatedWindowInfo(
- WindowState windowState, Rect boundsInScreen,
+ private static void addPopulatedWindowInfo(WindowState windowState, Region regionInScreen,
List<WindowInfo> out, Set<IBinder> tokenOut) {
final WindowInfo window = windowState.getWindowInfo();
- window.boundsInScreen.set(boundsInScreen);
+ window.regionInScreen.set(regionInScreen);
window.layer = tokenOut.size();
out.add(window);
tokenOut.add(window.token);
@@ -1293,7 +1306,7 @@ final class AccessibilityController {
private void populateVisibleWindowsOnScreenLocked(SparseArray<WindowState> outWindows) {
final List<WindowState> tempWindowStatesList = new ArrayList<>();
final DisplayContent dc = mService.getDefaultDisplayContentLocked();
- dc.forAllWindows((w) -> {
+ dc.forAllWindows(w -> {
if (w.isVisibleLw()) {
tempWindowStatesList.add(w);
}
@@ -1306,17 +1319,11 @@ final class AccessibilityController {
return;
}
- // TODO: Use Region instead to get rid of this complicated logic.
- // Check the tap exclude region of the parent window. If the tap exclude region
- // is empty, it means there is another can-receive-pointer-event view on top of
- // the region. Hence, we don't count the window as visible.
if (w.isVisibleLw() && parentWindow.getDisplayContent().isDefaultDisplay
- && parentWindow.hasTapExcludeRegion()
&& tempWindowStatesList.contains(parentWindow)) {
- tempWindowStatesList.add(
- tempWindowStatesList.lastIndexOf(parentWindow) + 1, w);
+ tempWindowStatesList.add(tempWindowStatesList.lastIndexOf(parentWindow), w);
}
- }, true /* traverseTopToBottom */);
+ }, false /* traverseTopToBottom */);
for (int i = 0; i < tempWindowStatesList.size(); i++) {
outWindows.put(i, tempWindowStatesList.get(i));
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 9c87ce8e1744..8f6f614bf17c 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1523,7 +1523,6 @@ final class ActivityRecord extends ConfigurationContainer {
stack.moveToFront(reason, task);
// Report top activity change to tracking services and WM
if (mRootActivityContainer.getTopResumedActivity() == this) {
- // TODO(b/111361570): Support multiple focused apps in WM
mAtmService.setResumedActivityUncheckLocked(this, reason);
}
return true;
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 18a57ae17fda..79098f17899e 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -565,7 +565,6 @@ class ActivityStack extends ConfigurationContainer {
+ reason);
setResumedActivity(record, reason + " - onActivityStateChanged");
if (record == mRootActivityContainer.getTopResumedActivity()) {
- // TODO(b/111361570): Support multiple focused apps in WM
mService.setResumedActivityUncheckLocked(record, reason);
}
mStackSupervisor.mRecentTasks.add(record.getTaskRecord());
@@ -3711,9 +3710,6 @@ class ActivityStack extends ConfigurationContainer {
if (nextFocusableStack != null) {
final ActivityRecord top = nextFocusableStack.topRunningActivityLocked();
if (top != null && top == mRootActivityContainer.getTopResumedActivity()) {
- // TODO(b/111361570): Remove this and update focused app per-display in
- // WindowManager every time an activity becomes resumed in
- // ActivityTaskManagerService#setResumedActivityUncheckLocked().
mService.setResumedActivityUncheckLocked(top, reason);
}
return;
@@ -5651,7 +5647,6 @@ class ActivityStack extends ConfigurationContainer {
// If the original state is resumed, there is no state change to update focused app.
// So here makes sure the activity focus is set if it is the top.
if (origState == RESUMED && r == mRootActivityContainer.getTopResumedActivity()) {
- // TODO(b/111361570): Support multiple focused apps in WM
mService.setResumedActivityUncheckLocked(r, reason);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 971a24d13643..c37ced55c563 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4912,7 +4912,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
void dumpActivityContainersLocked(PrintWriter pw) {
- pw.println("ACTIVITY MANAGER STARTER (dumpsys activity containers)");
+ pw.println("ACTIVITY MANAGER CONTAINERS (dumpsys activity containers)");
mRootActivityContainer.dumpChildrenNames(pw, " ");
pw.println(" ");
}
@@ -4928,6 +4928,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
* - the cmd arg isn't the flattened component name of an existing activity:
* dump all activity whose component contains the cmd as a substring
* - A hex number of the ActivityRecord object instance.
+ * <p>
+ * The caller should not hold lock when calling this method because it will wait for the
+ * activities to complete the dump.
*
* @param dumpVisibleStacksOnly dump activity with {@param name} only if in a visible stack
* @param dumpFocusedStackOnly dump activity with {@param name} only if in the focused stack
@@ -4980,29 +4983,28 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
private void dumpActivity(String prefix, FileDescriptor fd, PrintWriter pw,
final ActivityRecord r, String[] args, boolean dumpAll) {
String innerPrefix = prefix + " ";
+ IApplicationThread appThread = null;
synchronized (mGlobalLock) {
pw.print(prefix); pw.print("ACTIVITY "); pw.print(r.shortComponentName);
pw.print(" "); pw.print(Integer.toHexString(System.identityHashCode(r)));
pw.print(" pid=");
- if (r.hasProcess()) pw.println(r.app.getPid());
- else pw.println("(not running)");
+ if (r.hasProcess()) {
+ pw.println(r.app.getPid());
+ appThread = r.app.getThread();
+ } else {
+ pw.println("(not running)");
+ }
if (dumpAll) {
r.dump(pw, innerPrefix);
}
}
- if (r.attachedToProcess()) {
+ if (appThread != null) {
// flush anything that is already in the PrintWriter since the thread is going
// to write to the file descriptor directly
pw.flush();
- try {
- TransferPipe tp = new TransferPipe();
- try {
- r.app.getThread().dumpActivity(tp.getWriteFd(),
- r.appToken, innerPrefix, args);
- tp.go(fd);
- } finally {
- tp.kill();
- }
+ try (TransferPipe tp = new TransferPipe()) {
+ appThread.dumpActivity(tp.getWriteFd(), r.appToken, innerPrefix, args);
+ tp.go(fd);
} catch (IOException e) {
pw.println(innerPrefix + "Failure while dumping the activity: " + e);
} catch (RemoteException e) {
@@ -7063,10 +7065,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
public boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name,
String[] args, int opti, boolean dumpAll, boolean dumpVisibleStacksOnly,
boolean dumpFocusedStackOnly) {
- synchronized (mGlobalLock) {
- return ActivityTaskManagerService.this.dumpActivity(fd, pw, name, args, opti,
- dumpAll, dumpVisibleStacksOnly, dumpFocusedStackOnly);
- }
+ return ActivityTaskManagerService.this.dumpActivity(fd, pw, name, args, opti, dumpAll,
+ dumpVisibleStacksOnly, dumpFocusedStackOnly);
}
@Override
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 8007c0f316e0..d15081ca2665 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -260,9 +260,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
ActivityRecord mActivityRecord;
/**
- * See {@link #canTurnScreenOn()}
+ * @see #currentLaunchCanTurnScreenOn()
*/
- private boolean mCanTurnScreenOn = true;
+ private boolean mCurrentLaunchCanTurnScreenOn = true;
/**
* If we are running an animation, this determines the transition type. Must be one of
@@ -1002,7 +1002,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
+ " " + this);
mAppStopped = false;
// Allow the window to turn the screen on once the app is resumed again.
- setCanTurnScreenOn(true);
+ setCurrentLaunchCanTurnScreenOn(true);
if (!wasStopped) {
destroySurfaces(true /*cleanupOnResume*/);
}
@@ -2420,21 +2420,25 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
}
/**
- * Sets whether the current launch can turn the screen on. See {@link #canTurnScreenOn()}
+ * Sets whether the current launch can turn the screen on.
+ * @see #currentLaunchCanTurnScreenOn()
*/
- void setCanTurnScreenOn(boolean canTurnScreenOn) {
- mCanTurnScreenOn = canTurnScreenOn;
+ void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
+ mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
}
/**
* Indicates whether the current launch can turn the screen on. This is to prevent multiple
* relayouts from turning the screen back on. The screen should only turn on at most
* once per activity resume.
+ * <p>
+ * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
+ * or {@link ActivityRecord#canTurnScreenOn} is set.
*
- * @return true if the screen can be turned on.
+ * @return {@code true} if the activity is ready to turn on the screen.
*/
- boolean canTurnScreenOn() {
- return mCanTurnScreenOn;
+ boolean currentLaunchCanTurnScreenOn() {
+ return mCurrentLaunchCanTurnScreenOn;
}
/**
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index cf87203893cf..61ba69fdf404 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -284,6 +284,8 @@ public class DisplayPolicy {
/** See {@link #getNavigationBarFrameHeight} */
private int[] mNavigationBarFrameHeightForRotationDefault = new int[4];
+ private boolean mIsFreeformWindowOverlappingWithNavBar;
+
/** Cached value of {@link ScreenShapeHelper#getWindowOutsetBottomPx} */
@Px private int mWindowOutsetBottom;
@@ -2379,6 +2381,7 @@ public class DisplayPolicy {
mAllowLockscreenWhenOn = false;
mShowingDream = false;
mWindowSleepTokenNeeded = false;
+ mIsFreeformWindowOverlappingWithNavBar = false;
}
/**
@@ -2478,6 +2481,13 @@ public class DisplayPolicy {
}
}
+ // Check if the freeform window overlaps with the navigation bar area.
+ final WindowState navBarWin = hasNavigationBar() ? mNavigationBar : null;
+ if (!mIsFreeformWindowOverlappingWithNavBar && win.inFreeformWindowingMode()
+ && isOverlappingWithNavBar(win, navBarWin)) {
+ mIsFreeformWindowOverlappingWithNavBar = true;
+ }
+
// Also keep track of any windows that are dimming but not necessarily fullscreen in the
// docked stack.
if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
@@ -3458,7 +3468,11 @@ public class DisplayPolicy {
}
} else if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
- visibility = setNavBarOpaqueFlag(visibility);
+ if (mIsFreeformWindowOverlappingWithNavBar) {
+ visibility = setNavBarTranslucentFlag(visibility);
+ } else {
+ visibility = setNavBarOpaqueFlag(visibility);
+ }
} else if (fullscreenDrawsBackground) {
visibility = setNavBarTransparentFlag(visibility);
}
@@ -3747,4 +3761,14 @@ public class DisplayPolicy {
wm.removeView(mPointerLocationView);
mPointerLocationView = null;
}
+
+ @VisibleForTesting
+ static boolean isOverlappingWithNavBar(WindowState targetWindow, WindowState navBarWindow) {
+ if (navBarWindow == null || !navBarWindow.isVisibleLw()
+ || targetWindow.mAppToken == null || !targetWindow.isVisibleLw()) {
+ return false;
+ }
+
+ return Rect.intersects(targetWindow.getFrameLw(), navBarWindow.getFrameLw());
+ }
}
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index ca4749f7b365..422b6e58e0ed 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -43,11 +43,13 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS
import android.os.IBinder;
import android.os.RemoteException;
import android.os.Trace;
+import android.util.EventLog;
import android.util.Slog;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.policy.IKeyguardDismissCallback;
+import com.android.server.am.EventLogTags;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
@@ -142,6 +144,11 @@ class KeyguardController {
if (!keyguardChanged && !aodChanged) {
return;
}
+ EventLog.writeEvent(EventLogTags.AM_SET_KEYGUARD_SHOWN,
+ keyguardShowing ? 1 : 0,
+ aodShowing ? 1 : 0,
+ mKeyguardGoingAway ? 1 : 0,
+ "setKeyguardShown");
mKeyguardShowing = keyguardShowing;
mAodShowing = aodShowing;
mWindowManager.setAodShowing(aodShowing);
@@ -178,6 +185,11 @@ class KeyguardController {
mWindowManager.deferSurfaceLayout();
try {
setKeyguardGoingAway(true);
+ EventLog.writeEvent(EventLogTags.AM_SET_KEYGUARD_SHOWN,
+ 1 /* keyguardShowing */,
+ mAodShowing ? 1 : 0,
+ 1 /* keyguardGoingAway */,
+ "keyguardGoingAway");
mRootActivityContainer.getDefaultDisplay().mDisplayContent
.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
false /* alwaysKeepCurrent */, convertTransitFlags(flags),
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8b1baebbbbc0..a3ee1088bc37 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2393,10 +2393,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void prepareWindowToDisplayDuringRelayout(boolean wasVisible) {
// We need to turn on screen regardless of visibility.
- boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0;
+ final boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0
+ || (mAppToken != null && mAppToken.mActivityRecord.canTurnScreenOn());
// The screen will turn on if the following conditions are met
- // 1. The window has the flag FLAG_TURN_SCREEN_ON
+ // 1. The window has the flag FLAG_TURN_SCREEN_ON or ActivityRecord#canTurnScreenOn.
// 2. The WMS allows theater mode.
// 3. No AWT or the AWT allows the screen to be turned on. This should only be true once
// per resume to prevent the screen getting getting turned on for each relayout. Set
@@ -2410,7 +2411,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
boolean allowTheaterMode = mWmService.mAllowTheaterModeWakeFromLayout
|| Settings.Global.getInt(mWmService.mContext.getContentResolver(),
Settings.Global.THEATER_MODE_ON, 0) == 0;
- boolean canTurnScreenOn = mAppToken == null || mAppToken.canTurnScreenOn();
+ boolean canTurnScreenOn = mAppToken == null || mAppToken.currentLaunchCanTurnScreenOn();
if (allowTheaterMode && canTurnScreenOn && !mPowerManagerWrapper.isInteractive()) {
if (DEBUG_VISIBILITY || DEBUG_POWER) {
@@ -2421,7 +2422,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
if (mAppToken != null) {
- mAppToken.setCanTurnScreenOn(false);
+ mAppToken.setCurrentLaunchCanTurnScreenOn(false);
}
}
diff --git a/services/core/java/com/android/server/wm/utils/RegionUtils.java b/services/core/java/com/android/server/wm/utils/RegionUtils.java
index b1b30701df4f..ce7776f270fd 100644
--- a/services/core/java/com/android/server/wm/utils/RegionUtils.java
+++ b/services/core/java/com/android/server/wm/utils/RegionUtils.java
@@ -50,6 +50,20 @@ public class RegionUtils {
/**
* Applies actions on each rect contained within a {@code Region}.
*
+ * @param region the given region.
+ * @param rectConsumer the action holder.
+ */
+ public static void forEachRect(Region region, Consumer<Rect> rectConsumer) {
+ final RegionIterator it = new RegionIterator(region);
+ final Rect rect = new Rect();
+ while (it.next(rect)) {
+ rectConsumer.accept(rect);
+ }
+ }
+
+ /**
+ * Applies actions on each rect contained within a {@code Region}.
+ *
* Order is bottom to top, then right to left.
*
* @param region the given region.
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java
index 73b3b8b1ce3c..a785300e98a3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/color/DisplayTransformManagerTest.java
@@ -19,6 +19,7 @@ package com.android.server.display.color;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY;
+import static com.android.server.display.color.DisplayTransformManager.PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE;
import static com.android.server.display.color.DisplayTransformManager.PERSISTENT_PROPERTY_DISPLAY_COLOR;
import static com.android.server.display.color.DisplayTransformManager.PERSISTENT_PROPERTY_SATURATION;
@@ -28,6 +29,7 @@ import static org.mockito.ArgumentMatchers.any;
import android.hardware.display.ColorDisplayManager;
import android.os.SystemProperties;
+import android.view.Display;
import androidx.test.runner.AndroidJUnit4;
@@ -79,7 +81,7 @@ public class DisplayTransformManagerTest {
@Test
public void setColorMode_natural() {
- mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix);
+ mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix, -1);
assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR))
.isEqualTo("0" /* managed */);
assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION))
@@ -88,7 +90,7 @@ public class DisplayTransformManagerTest {
@Test
public void setColorMode_boosted() {
- mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED, mNightDisplayMatrix);
+ mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED, mNightDisplayMatrix, -1);
assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR))
.isEqualTo("0" /* managed */);
@@ -98,7 +100,7 @@ public class DisplayTransformManagerTest {
@Test
public void setColorMode_saturated() {
- mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED, mNightDisplayMatrix);
+ mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED, mNightDisplayMatrix, -1);
assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR))
.isEqualTo("1" /* unmanaged */);
assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION))
@@ -107,7 +109,7 @@ public class DisplayTransformManagerTest {
@Test
public void setColorMode_automatic() {
- mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC, mNightDisplayMatrix);
+ mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC, mNightDisplayMatrix, -1);
assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR))
.isEqualTo("2" /* enhanced */);
assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION))
@@ -116,7 +118,7 @@ public class DisplayTransformManagerTest {
@Test
public void setColorMode_vendor() {
- mDtm.setColorMode(0x100, mNightDisplayMatrix);
+ mDtm.setColorMode(0x100, mNightDisplayMatrix, -1);
assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR))
.isEqualTo(Integer.toString(0x100) /* pass-through */);
assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION))
@@ -125,10 +127,38 @@ public class DisplayTransformManagerTest {
@Test
public void setColorMode_outOfBounds() {
- mDtm.setColorMode(0x50, mNightDisplayMatrix);
+ mDtm.setColorMode(0x50, mNightDisplayMatrix, -1);
assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR))
.isEqualTo(null);
assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION))
.isEqualTo(null);
}
+
+ @Test
+ public void setColorMode_withoutColorSpace() {
+ String magicPropertyValue = "magic";
+
+ // Start with a known state, which we expect to remain unmodified
+ SystemProperties.set(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE, magicPropertyValue);
+
+ mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix,
+ Display.COLOR_MODE_INVALID);
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE))
+ .isEqualTo(magicPropertyValue);
+ }
+
+ @Test
+ public void setColorMode_withColorSpace() {
+ String magicPropertyValue = "magic";
+ int testPropertyValue = Display.COLOR_MODE_SRGB;
+
+ // Start with a known state, which we expect to get modified
+ SystemProperties.set(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE, magicPropertyValue);
+
+ mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix,
+ testPropertyValue);
+ assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE))
+ .isEqualTo(Integer.toString(testPropertyValue));
+ }
+
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
index 22408cc05b93..e12532931e7c 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityWindowManagerTest.java
@@ -238,7 +238,7 @@ public class AccessibilityWindowManagerTest {
windowInfo.type = AccessibilityWindowInfo.TYPE_APPLICATION;
windowInfo.token = token.asBinder();
windowInfo.layer = 0;
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
mWindowInfos.set(0, windowInfo);
mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
@@ -305,67 +305,73 @@ public class AccessibilityWindowManagerTest {
}
@Test
- public void computePartialInteractiveRegionForWindow_wholeWindowVisible_returnWholeRegion() {
+ public void computePartialInteractiveRegionForWindow_wholeVisible_returnWholeRegion() {
// Updates top 2 z-order WindowInfo are whole visible.
WindowInfo windowInfo = mWindowInfos.get(0);
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2);
+ windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2);
windowInfo = mWindowInfos.get(1);
- windowInfo.boundsInScreen.set(0, SCREEN_HEIGHT / 2,
- SCREEN_WIDTH, SCREEN_HEIGHT);
+ windowInfo.regionInScreen.set(0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT);
mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
final Region outBounds = new Region();
int windowId = a11yWindows.get(0).getId();
- mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
- windowId, outBounds);
+ mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds);
assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH));
assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT / 2));
windowId = a11yWindows.get(1).getId();
- mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
- windowId, outBounds);
+ mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds);
assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH));
assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT / 2));
}
@Test
- public void computePartialInteractiveRegionForWindow_halfWindowVisible_returnHalfRegion() {
+ public void computePartialInteractiveRegionForWindow_halfVisible_returnHalfRegion() {
// Updates z-order #1 WindowInfo is half visible
WindowInfo windowInfo = mWindowInfos.get(0);
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2);
- windowInfo = mWindowInfos.get(1);
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 2);
mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
final Region outBounds = new Region();
int windowId = a11yWindows.get(1).getId();
- mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
- windowId, outBounds);
+ mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds);
assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH));
assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT / 2));
}
@Test
- public void computePartialInteractiveRegionForWindow_windowNotVisible_returnEmptyRegion() {
- // Updates z-order #1 WindowInfo is not visible
+ public void computePartialInteractiveRegionForWindow_notVisible_returnEmptyRegion() {
+ // Since z-order #0 WindowInfo is full screen, z-order #1 WindowInfo should be invisible.
+ final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
+ final Region outBounds = new Region();
+ int windowId = a11yWindows.get(1).getId();
+
+ mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds);
+ assertTrue(outBounds.getBounds().isEmpty());
+ }
+
+ @Test
+ public void computePartialInteractiveRegionForWindow_partialVisible_returnVisibleRegion() {
+ // Updates z-order #0 WindowInfo to have two interact-able areas.
+ Region region = new Region(0, 0, SCREEN_WIDTH, 200);
+ region.op(0, SCREEN_HEIGHT - 200, SCREEN_WIDTH, SCREEN_HEIGHT, Region.Op.UNION);
WindowInfo windowInfo = mWindowInfos.get(0);
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
- windowInfo = mWindowInfos.get(1);
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ windowInfo.regionInScreen.set(region);
mA11yWindowManager.onWindowsForAccessibilityChanged(SEND_ON_WINDOW_CHANGES, mWindowInfos);
final List<AccessibilityWindowInfo> a11yWindows = mA11yWindowManager.getWindowListLocked();
final Region outBounds = new Region();
int windowId = a11yWindows.get(1).getId();
- mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
- windowId, outBounds);
- assertTrue(outBounds.getBounds().isEmpty());
+ mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(windowId, outBounds);
+ assertFalse(outBounds.getBounds().isEmpty());
+ assertThat(outBounds.getBounds().width(), is(SCREEN_WIDTH));
+ assertThat(outBounds.getBounds().height(), is(SCREEN_HEIGHT - 400));
}
@Test
@@ -588,7 +594,7 @@ public class AccessibilityWindowManagerTest {
windowInfo.type = AccessibilityWindowInfo.TYPE_APPLICATION;
windowInfo.token = windowToken.asBinder();
windowInfo.layer = layer;
- windowInfo.boundsInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ windowInfo.regionInScreen.set(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
mWindowInfos.add(windowInfo);
}
diff --git a/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
index fb2913b09ace..a19b3872949e 100644
--- a/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/color/ColorDisplayServiceTest.java
@@ -18,13 +18,19 @@ package com.android.server.display.color;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.res.Resources;
import android.hardware.display.ColorDisplayManager;
import android.hardware.display.Time;
import android.os.Handler;
@@ -33,6 +39,7 @@ import android.provider.Settings;
import android.provider.Settings.Secure;
import android.provider.Settings.System;
import android.test.mock.MockContentResolver;
+import android.view.Display;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -73,6 +80,8 @@ public class ColorDisplayServiceTest {
private ColorDisplayService mCds;
private ColorDisplayService.BinderService mBinderService;
+ private Resources mResourcesSpy;
+
@BeforeClass
public static void setDtm() {
final DisplayTransformManager dtm = Mockito.mock(DisplayTransformManager.class);
@@ -84,6 +93,9 @@ public class ColorDisplayServiceTest {
mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
doReturn(mContext).when(mContext).getApplicationContext();
+ mResourcesSpy = Mockito.spy(mContext.getResources());
+ when(mContext.getResources()).thenReturn(mResourcesSpy);
+
mUserId = ActivityManager.getCurrentUser();
final MockContentResolver cr = new MockContentResolver(mContext);
@@ -1050,6 +1062,80 @@ public class ColorDisplayServiceTest {
assertDwbActive(true);
}
+ @Test
+ public void compositionColorSpaces_noResources() {
+ final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class);
+ reset(dtm);
+
+ when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorModes))
+ .thenReturn(new int[] {});
+ when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorSpaces))
+ .thenReturn(new int[] {});
+ setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
+ startService();
+ verify(dtm).setColorMode(eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(),
+ eq(Display.COLOR_MODE_INVALID));
+ }
+
+ @Test
+ public void compositionColorSpaces_invalidResources() {
+ final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class);
+ reset(dtm);
+
+ when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorModes))
+ .thenReturn(new int[] {
+ ColorDisplayManager.COLOR_MODE_NATURAL,
+ // Missing second color mode
+ });
+ when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorSpaces))
+ .thenReturn(new int[] {
+ Display.COLOR_MODE_SRGB,
+ Display.COLOR_MODE_DISPLAY_P3
+ });
+ setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
+ startService();
+ verify(dtm).setColorMode(eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(),
+ eq(Display.COLOR_MODE_INVALID));
+ }
+
+ @Test
+ public void compositionColorSpaces_validResources_validColorMode() {
+ final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class);
+ reset(dtm);
+
+ when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorModes))
+ .thenReturn(new int[] {
+ ColorDisplayManager.COLOR_MODE_NATURAL
+ });
+ when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorSpaces))
+ .thenReturn(new int[] {
+ Display.COLOR_MODE_SRGB,
+ });
+ setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
+ startService();
+ verify(dtm).setColorMode(eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(),
+ eq(Display.COLOR_MODE_SRGB));
+ }
+
+ @Test
+ public void compositionColorSpaces_validResources_invalidColorMode() {
+ final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class);
+ reset(dtm);
+
+ when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorModes))
+ .thenReturn(new int[] {
+ ColorDisplayManager.COLOR_MODE_NATURAL
+ });
+ when(mResourcesSpy.getIntArray(R.array.config_displayCompositionColorSpaces))
+ .thenReturn(new int[] {
+ Display.COLOR_MODE_SRGB,
+ });
+ setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED);
+ startService();
+ verify(dtm).setColorMode(eq(ColorDisplayManager.COLOR_MODE_BOOSTED), any(),
+ eq(Display.COLOR_MODE_INVALID));
+ }
+
/**
* Configures Night display to use a custom schedule.
*
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 6061d51f3d79..8c3373faa0d4 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -156,7 +156,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
mService.setUsageStats(mUsageStats);
mService.setAccessibilityManager(accessibilityManager);
mService.mScreenOn = false;
- mService.mInCall = false;
+ mService.mInCallStateOffHook = false;
mService.mNotificationPulseEnabled = true;
}
@@ -681,7 +681,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
mService.buzzBeepBlinkLocked(r);
Mockito.reset(mRingtonePlayer);
- mService.mInCall = true;
+ mService.mInCallStateOffHook = true;
mService.buzzBeepBlinkLocked(r);
verify(mService, times(1)).playInCallNotification();
@@ -1137,7 +1137,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
@Test
public void testLightsInCall() {
- mService.mInCall = true;
+ mService.mInCallStateOffHook = true;
NotificationRecord r = getLightsNotification();
mService.buzzBeepBlinkLocked(r);
verifyNeverLights();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index 1684f97d28e3..6a3c81ab73bc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -32,6 +32,7 @@ import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLES
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -49,10 +50,12 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.Surface;
import android.view.WindowManager;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import org.junit.Test;
@@ -273,4 +276,37 @@ public class DisplayPolicyTests extends WindowTestsBase {
win.mHasSurface = true;
return win;
}
+
+ @Test
+ @FlakyTest(bugId = 131005232)
+ public void testOverlappingWithNavBar() {
+ final WindowState targetWin = createApplicationWindow();
+ final WindowFrames winFrame = targetWin.getWindowFrames();
+ winFrame.mFrame.set(new Rect(100, 100, 200, 200));
+
+ final WindowState navigationBar = createNavigationBarWindow();
+
+ navigationBar.getFrameLw().set(new Rect(100, 200, 200, 300));
+
+ assertFalse("Freeform is overlapping with navigation bar",
+ DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar));
+
+ winFrame.mFrame.set(new Rect(100, 101, 200, 201));
+ assertTrue("Freeform should be overlapping with navigation bar (bottom)",
+ DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar));
+
+ winFrame.mFrame.set(new Rect(99, 200, 199, 300));
+ assertTrue("Freeform should be overlapping with navigation bar (right)",
+ DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar));
+
+ winFrame.mFrame.set(new Rect(199, 200, 299, 300));
+ assertTrue("Freeform should be overlapping with navigation bar (left)",
+ DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar));
+ }
+
+ private WindowState createNavigationBarWindow() {
+ final WindowState win = createWindow(null, TYPE_NAVIGATION_BAR, "NavigationBar");
+ win.mHasSurface = true;
+ return win;
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 1b57c7924ecb..36698eae274c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -302,43 +302,38 @@ public class WindowStateTests extends WindowTestsBase {
@Test
public void testPrepareWindowToDisplayDuringRelayout() {
- testPrepareWindowToDisplayDuringRelayout(false /*wasVisible*/);
- testPrepareWindowToDisplayDuringRelayout(true /*wasVisible*/);
-
- // Call prepareWindowToDisplayDuringRelayout for a window without FLAG_TURN_SCREEN_ON
- // before calling prepareWindowToDisplayDuringRelayout for windows with flag in the same
- // appWindowToken.
+ // Call prepareWindowToDisplayDuringRelayout for a window without FLAG_TURN_SCREEN_ON before
+ // calling setCurrentLaunchCanTurnScreenOn for windows with flag in the same appWindowToken.
final AppWindowToken appWindowToken = createAppWindowToken(mDisplayContent,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
final WindowState first = createWindow(null, TYPE_APPLICATION, appWindowToken, "first");
final WindowState second = createWindow(null, TYPE_APPLICATION, appWindowToken, "second");
second.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
- reset(sPowerManagerWrapper);
- first.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/);
- verify(sPowerManagerWrapper, never()).wakeUp(anyLong(), anyInt(), anyString());
- assertTrue(appWindowToken.canTurnScreenOn());
-
- reset(sPowerManagerWrapper);
- second.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/);
- verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString());
- assertFalse(appWindowToken.canTurnScreenOn());
+ testPrepareWindowToDisplayDuringRelayout(first, false /* expectedWakeupCalled */,
+ true /* expectedCurrentLaunchCanTurnScreenOn */);
+ testPrepareWindowToDisplayDuringRelayout(second, true /* expectedWakeupCalled */,
+ false /* expectedCurrentLaunchCanTurnScreenOn */);
// Call prepareWindowToDisplayDuringRelayout for two window that have FLAG_TURN_SCREEN_ON
// from the same appWindowToken. Only one should trigger the wakeup.
- appWindowToken.setCanTurnScreenOn(true);
+ appWindowToken.setCurrentLaunchCanTurnScreenOn(true);
first.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
second.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
- reset(sPowerManagerWrapper);
- first.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/);
- verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString());
- assertFalse(appWindowToken.canTurnScreenOn());
+ testPrepareWindowToDisplayDuringRelayout(first, true /* expectedWakeupCalled */,
+ false /* expectedCurrentLaunchCanTurnScreenOn */);
+ testPrepareWindowToDisplayDuringRelayout(second, false /* expectedWakeupCalled */,
+ false /* expectedCurrentLaunchCanTurnScreenOn */);
- reset(sPowerManagerWrapper);
- second.prepareWindowToDisplayDuringRelayout(false /*wasVisible*/);
- verify(sPowerManagerWrapper, never()).wakeUp(anyLong(), anyInt(), anyString());
- assertFalse(appWindowToken.canTurnScreenOn());
+ // Without window flags, the state of ActivityRecord.canTurnScreenOn should still be able to
+ // turn on the screen.
+ appWindowToken.setCurrentLaunchCanTurnScreenOn(true);
+ first.mAttrs.flags &= ~WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
+ doReturn(true).when(appWindowToken.mActivityRecord).canTurnScreenOn();
+
+ testPrepareWindowToDisplayDuringRelayout(first, true /* expectedWakeupCalled */,
+ false /* expectedCurrentLaunchCanTurnScreenOn */);
// Call prepareWindowToDisplayDuringRelayout for a windows that are not children of an
// appWindowToken. Both windows have the FLAG_TURNS_SCREEN_ON so both should call wakeup
@@ -360,6 +355,22 @@ public class WindowStateTests extends WindowTestsBase {
verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString());
}
+ private void testPrepareWindowToDisplayDuringRelayout(WindowState appWindow,
+ boolean expectedWakeupCalled, boolean expectedCurrentLaunchCanTurnScreenOn) {
+ reset(sPowerManagerWrapper);
+ appWindow.prepareWindowToDisplayDuringRelayout(false /* wasVisible */);
+
+ if (expectedWakeupCalled) {
+ verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString());
+ } else {
+ verify(sPowerManagerWrapper, never()).wakeUp(anyLong(), anyInt(), anyString());
+ }
+ // If wakeup is expected to be called, the currentLaunchCanTurnScreenOn should be false
+ // because the state will be consumed.
+ assertThat(appWindow.mAppToken.currentLaunchCanTurnScreenOn(),
+ is(expectedCurrentLaunchCanTurnScreenOn));
+ }
+
@Test
public void testCanAffectSystemUiFlags() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
@@ -487,15 +498,6 @@ public class WindowStateTests extends WindowTestsBase {
assertThat(app.getWmDisplayCutout().getDisplayCutout(), is(cutout.inset(7, 10, 5, 20)));
}
- private void testPrepareWindowToDisplayDuringRelayout(boolean wasVisible) {
- reset(sPowerManagerWrapper);
- final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
- root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
-
- root.prepareWindowToDisplayDuringRelayout(wasVisible /*wasVisible*/);
- verify(sPowerManagerWrapper).wakeUp(anyLong(), anyInt(), anyString());
- }
-
@Test
public void testVisibilityChangeSwitchUser() {
final WindowState window = createWindow(null, TYPE_APPLICATION, "app");
diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java
index e9a5ff70a7cc..4d8c7d930bde 100644
--- a/test-mock/src/android/test/mock/MockContentProvider.java
+++ b/test-mock/src/android/test/mock/MockContentProvider.java
@@ -16,6 +16,7 @@
package android.test.mock;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentProvider;
import android.content.ContentProviderOperation;
@@ -23,6 +24,7 @@ import android.content.ContentProviderResult;
import android.content.ContentValues;
import android.content.Context;
import android.content.IContentProvider;
+import android.content.Intent;
import android.content.OperationApplicationException;
import android.content.pm.PathPermission;
import android.content.pm.ProviderInfo;
@@ -154,6 +156,11 @@ public class MockContentProvider extends ContentProvider {
ICancellationSignal cancellationSignal) throws RemoteException {
return MockContentProvider.this.refresh(url, args);
}
+
+ @Override
+ public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) {
+ return MockContentProvider.this.checkUriPermission(uri, uid, modeFlags);
+ }
}
private final InversionIContentProvider mIContentProvider = new InversionIContentProvider();
@@ -266,6 +273,12 @@ public class MockContentProvider extends ContentProvider {
throw new UnsupportedOperationException("unimplemented mock method call");
}
+ /** {@hide} */
+ @Override
+ public int checkUriPermission(@NonNull Uri uri, int uid, @Intent.AccessUriMode int modeFlags) {
+ throw new UnsupportedOperationException("unimplemented mock method call");
+ }
+
/**
* Returns IContentProvider which calls back same methods in this class.
* By overriding this class, we avoid the mechanism hidden behind ContentProvider
diff --git a/test-mock/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java
index fc2a4644b994..b072d7440de4 100644
--- a/test-mock/src/android/test/mock/MockIContentProvider.java
+++ b/test-mock/src/android/test/mock/MockIContentProvider.java
@@ -16,12 +16,14 @@
package android.test.mock;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentValues;
import android.content.EntityIterator;
import android.content.IContentProvider;
+import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
@@ -144,4 +146,10 @@ public class MockIContentProvider implements IContentProvider {
ICancellationSignal cancellationSignal) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
+
+ /** {@hide} */
+ @Override
+ public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) {
+ throw new UnsupportedOperationException("unimplemented mock method call");
+ }
}
diff --git a/tools/lock_agent/Android.bp b/tools/lock_agent/Android.bp
index 408946b28836..79dce4a8ce09 100644
--- a/tools/lock_agent/Android.bp
+++ b/tools/lock_agent/Android.bp
@@ -12,13 +12,9 @@ cc_library {
],
sdk_version: "current",
stl: "c++_static",
- include_dirs: [
- // NDK headers aren't available in platform NDK builds.
- "libnativehelper/include_jni",
- // Use ScopedUtfChars.
- "libnativehelper/header_only_include",
- ],
header_libs: [
+ // Use ScopedUtfChars.
+ "libnativehelper_header_only",
"libopenjdkjvmti_headers",
],
compile_multilib: "both",
@@ -32,13 +28,9 @@ cc_binary_host {
"libz",
"slicer",
],
- include_dirs: [
- // NDK headers aren't available in platform NDK builds.
- "libnativehelper/include_jni",
- // Use ScopedUtfChars.
- "libnativehelper/header_only_include",
- ],
header_libs: [
+ // Use ScopedUtfChars.
+ "libnativehelper_header_only",
"libopenjdkjvmti_headers",
],
}