summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java5
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java8
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java35
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java30
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java66
-rw-r--r--services/core/java/com/android/server/wm/AsyncRotationController.java26
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java6
-rw-r--r--services/core/java/com/android/server/wm/Transition.java11
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java16
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java6
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java66
-rw-r--r--services/tests/servicestests/res/xml/user_100_v9.xml20
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java90
-rw-r--r--services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java5
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java52
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java11
21 files changed, 419 insertions, 58 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 9ff338e8d5ab..42a4e7202c82 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -281,6 +281,8 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
public interface SwipeListener {
void onSwipeUp();
+ /** */
+ void onSwipeDown();
}
@VisibleForTesting
@@ -543,6 +545,11 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
if (mSwipeListener != null) {
mSwipeListener.onSwipeUp();
}
+ } else if (getTranslationY() > TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ MIN_DRAG_SIZE, getResources().getDisplayMetrics())) {
+ if (mSwipeListener != null) {
+ mSwipeListener.onSwipeDown();
+ }
}
}
return true;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index e18050d77847..d3dbc4e8d6e1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -309,6 +309,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
"swipeUpOnBouncer");
}
}
+
+ @Override
+ public void onSwipeDown() {
+ mViewMediatorCallback.onBouncerSwipeDown();
+ }
};
private final ConfigurationController.ConfigurationListener mConfigurationListener =
new ConfigurationController.ConfigurationListener() {
diff --git a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
index 50f8f7e61230..14ec27ae6739 100644
--- a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
@@ -104,4 +104,9 @@ public interface ViewMediatorCallback {
* Call when cancel button is pressed in bouncer.
*/
void onCancelClicked();
+
+ /**
+ * Determines if bouncer has swiped down.
+ */
+ void onBouncerSwipeDown();
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index cba717038871..df6007ddedfb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -874,6 +874,11 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
}
@Override
+ public void onBouncerSwipeDown() {
+ mKeyguardViewControllerLazy.get().reset(/* hideBouncerWhenShowing= */ true);
+ }
+
+ @Override
public void playTrustedSound() {
KeyguardViewMediator.this.playTrustedSound();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
index 9cabd35cb1e5..52e172620a52 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt
@@ -22,6 +22,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.shade.ShadeExpansionStateManager
import org.junit.Assert
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -48,6 +49,7 @@ class AuthDialogPanelInteractionDetectorTest : SysuiTestCase() {
AuthDialogPanelInteractionDetector(shadeExpansionStateManager, mContext.mainExecutor)
}
+ @Ignore("b/316929376")
@Test
fun testEnableDetector_expandWithTrack_shouldPostRunnable() {
detector.enable(action)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index cfe3b0d2a803..eef5c1dc5309 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -771,6 +771,11 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
assertTrue(mViewMediator.isShowingAndNotOccluded());
}
+ @Test
+ public void testBouncerSwipeDown() {
+ mViewMediator.getViewMediatorCallback().onBouncerSwipeDown();
+ verify(mStatusBarKeyguardViewManager).reset(true);
+ }
private void createAndStartViewMediator() {
createAndStartViewMediator(false);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 8e7d27795c07..2519f4e7f3e3 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -388,11 +388,19 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
@Override
public void onMotionEvent(MotionEvent transformedEvent, MotionEvent rawEvent,
int policyFlags) {
+ if (!mInstalled) {
+ Slog.w(TAG, "onMotionEvent called before input filter installed!");
+ return;
+ }
sendInputEvent(transformedEvent, policyFlags);
}
@Override
public void onKeyEvent(KeyEvent event, int policyFlags) {
+ if (!mInstalled) {
+ Slog.w(TAG, "onKeyEvent called before input filter installed!");
+ return;
+ }
sendInputEvent(event, policyFlags);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 647087de1c04..2e29941ee43b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -9522,14 +9522,19 @@ public class NotificationManagerService extends SystemService {
* Determine whether the userId applies to the notification in question, either because
* they match exactly, or one of them is USER_ALL (which is treated as a wildcard).
*/
- private boolean notificationMatchesUserId(NotificationRecord r, int userId) {
- return
+ private static boolean notificationMatchesUserId(NotificationRecord r, int userId,
+ boolean isAutogroupSummary) {
+ if (isAutogroupSummary) {
+ return r.getUserId() == userId;
+ } else {
+ return
// looking for USER_ALL notifications? match everything
- userId == UserHandle.USER_ALL
- // a notification sent to USER_ALL matches any query
- || r.getUserId() == UserHandle.USER_ALL
- // an exact user match
- || r.getUserId() == userId;
+ userId == UserHandle.USER_ALL
+ // a notification sent to USER_ALL matches any query
+ || r.getUserId() == UserHandle.USER_ALL
+ // an exact user match
+ || r.getUserId() == userId;
+ }
}
/**
@@ -9538,7 +9543,7 @@ public class NotificationManagerService extends SystemService {
* because it matches one of the users profiles.
*/
private boolean notificationMatchesCurrentProfiles(NotificationRecord r, int userId) {
- return notificationMatchesUserId(r, userId)
+ return notificationMatchesUserId(r, userId, false)
|| mUserProfiles.isCurrentProfile(r.getUserId());
}
@@ -9607,7 +9612,7 @@ public class NotificationManagerService extends SystemService {
if (!notificationMatchesCurrentProfiles(r, userId)) {
continue;
}
- } else if (!notificationMatchesUserId(r, userId)) {
+ } else if (!notificationMatchesUserId(r, userId, false)) {
continue;
}
// Don't remove notifications to all, if there's no package name specified
@@ -9845,7 +9850,7 @@ public class NotificationManagerService extends SystemService {
final int len = list.size();
for (int i = 0; i < len; i++) {
NotificationRecord r = list.get(i);
- if (notificationMatchesUserId(r, userId) && r.getGroupKey().equals(groupKey)
+ if (notificationMatchesUserId(r, userId, false) && r.getGroupKey().equals(groupKey)
&& r.getSbn().getPackageName().equals(pkg)) {
records.add(r);
}
@@ -9887,8 +9892,8 @@ public class NotificationManagerService extends SystemService {
final int len = list.size();
for (int i = 0; i < len; i++) {
NotificationRecord r = list.get(i);
- if (notificationMatchesUserId(r, userId) && r.getSbn().getId() == id &&
- TextUtils.equals(r.getSbn().getTag(), tag)
+ if (notificationMatchesUserId(r, userId, (r.getFlags() & GroupHelper.BASE_FLAGS) != 0)
+ && r.getSbn().getId() == id && TextUtils.equals(r.getSbn().getTag(), tag)
&& r.getSbn().getPackageName().equals(pkg)) {
return r;
}
@@ -9903,8 +9908,8 @@ public class NotificationManagerService extends SystemService {
final int len = list.size();
for (int i = 0; i < len; i++) {
NotificationRecord r = list.get(i);
- if (notificationMatchesUserId(r, userId) && r.getSbn().getId() == id &&
- TextUtils.equals(r.getSbn().getTag(), tag)
+ if (notificationMatchesUserId(r, userId, false) && r.getSbn().getId() == id
+ && TextUtils.equals(r.getSbn().getTag(), tag)
&& r.getSbn().getPackageName().equals(pkg)) {
matching.add(r);
}
@@ -9937,7 +9942,7 @@ public class NotificationManagerService extends SystemService {
final int n = mEnqueuedNotifications.size();
for (int i = 0; i < n; i++) {
NotificationRecord r = mEnqueuedNotifications.get(i);
- if (notificationMatchesUserId(r, userId)
+ if (notificationMatchesUserId(r, userId, false)
&& r.getSbn().getId() == id
&& TextUtils.equals(r.getSbn().getTag(), tag)
&& r.getSbn().getPackageName().equals(pkg)) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index b03fb31fbb1e..80e1c7e9697b 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2667,7 +2667,8 @@ public class UserManagerService extends IUserManager.Stub {
}
}
- private void setUserRestrictionInner(int userId, @NonNull String key, boolean value) {
+ @VisibleForTesting
+ void setUserRestrictionInner(int userId, @NonNull String key, boolean value) {
if (!UserRestrictionsUtils.isValidRestriction(key)) {
Slog.e(LOG_TAG, "Setting invalid restriction " + key);
return;
@@ -3704,7 +3705,8 @@ public class UserManagerService extends IUserManager.Stub {
if (type == XmlPullParser.START_TAG) {
final String name = parser.getName();
if (name.equals(TAG_USER)) {
- UserData userData = readUserLP(parser.getAttributeInt(null, ATTR_ID));
+ UserData userData = readUserLP(parser.getAttributeInt(null, ATTR_ID),
+ mUserVersion);
if (userData != null) {
synchronized (mUsersLock) {
@@ -4277,11 +4279,11 @@ public class UserManagerService extends IUserManager.Stub {
UserRestrictionsUtils.writeRestrictions(serializer,
mDevicePolicyUserRestrictions.getRestrictions(UserHandle.USER_ALL),
- TAG_DEVICE_POLICY_RESTRICTIONS);
+ TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS);
UserRestrictionsUtils.writeRestrictions(serializer,
mDevicePolicyUserRestrictions.getRestrictions(userInfo.id),
- TAG_DEVICE_POLICY_RESTRICTIONS);
+ TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS);
}
if (userData.account != null) {
@@ -4385,7 +4387,7 @@ public class UserManagerService extends IUserManager.Stub {
}
@GuardedBy({"mPackagesLock"})
- private UserData readUserLP(int id) {
+ private UserData readUserLP(int id, int userVersion) {
try (ResilientAtomicFile file = getUserFile(id)) {
FileInputStream fis = null;
try {
@@ -4394,19 +4396,19 @@ public class UserManagerService extends IUserManager.Stub {
Slog.e(LOG_TAG, "User info not found, returning null, user id: " + id);
return null;
}
- return readUserLP(id, fis);
+ return readUserLP(id, fis, userVersion);
} catch (Exception e) {
// Remove corrupted file and retry.
Slog.e(LOG_TAG, "Error reading user info, user id: " + id);
file.failRead(fis, e);
- return readUserLP(id);
+ return readUserLP(id, userVersion);
}
}
}
@GuardedBy({"mPackagesLock"})
@VisibleForTesting
- UserData readUserLP(int id, InputStream is) throws IOException,
+ UserData readUserLP(int id, InputStream is, int userVersion) throws IOException,
XmlPullParserException {
int flags = 0;
String userType = null;
@@ -4499,7 +4501,17 @@ public class UserManagerService extends IUserManager.Stub {
} else if (TAG_DEVICE_POLICY_RESTRICTIONS.equals(tag)) {
legacyLocalRestrictions = UserRestrictionsUtils.readRestrictions(parser);
} else if (TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS.equals(tag)) {
- localRestrictions = UserRestrictionsUtils.readRestrictions(parser);
+ if (userVersion < 10) {
+ // Prior to version 10, the local user restrictions were stored as sub tags
+ // grouped by the user id of the source user. The source is no longer stored
+ // on versions 10+ as this is now stored in the DevicePolicyEngine.
+ RestrictionsSet oldLocalRestrictions =
+ RestrictionsSet.readRestrictions(
+ parser, TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS);
+ localRestrictions = oldLocalRestrictions.mergeAll();
+ } else {
+ localRestrictions = UserRestrictionsUtils.readRestrictions(parser);
+ }
} else if (TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS.equals(tag)) {
globalRestrictions = UserRestrictionsUtils.readRestrictions(parser);
} else if (TAG_ACCOUNT.equals(tag)) {
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index f3001133338a..b3ae2ee30f22 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -1280,45 +1280,53 @@ final class AccessibilityController {
}
void drawIfNeeded(SurfaceControl.Transaction t) {
+ // Drawing variables (alpha, dirty rect, and bounds) access is synchronized
+ // using WindowManagerGlobalLock. Grab copies of these values before
+ // drawing on the canvas so that drawing can be performed outside of the lock.
+ int alpha;
+ Rect drawingRect = null;
+ Region drawingBounds = null;
synchronized (mService.mGlobalLock) {
if (!mInvalidated) {
return;
}
mInvalidated = false;
- if (mAlpha > 0) {
- Canvas canvas = null;
- try {
- // Empty dirty rectangle means unspecified.
- if (mDirtyRect.isEmpty()) {
- mBounds.getBounds(mDirtyRect);
- }
- mDirtyRect.inset(-mHalfBorderWidth, -mHalfBorderWidth);
- canvas = mSurface.lockCanvas(mDirtyRect);
- if (DEBUG_VIEWPORT_WINDOW) {
- Slog.i(LOG_TAG, "Dirty rect: " + mDirtyRect);
- }
- } catch (IllegalArgumentException iae) {
- /* ignore */
- } catch (Surface.OutOfResourcesException oore) {
- /* ignore */
- }
- if (canvas == null) {
- return;
+
+ alpha = mAlpha;
+ if (alpha > 0) {
+ drawingBounds = new Region(mBounds);
+ // Empty dirty rectangle means unspecified.
+ if (mDirtyRect.isEmpty()) {
+ mBounds.getBounds(mDirtyRect);
}
+ mDirtyRect.inset(-mHalfBorderWidth, -mHalfBorderWidth);
+ drawingRect = new Rect(mDirtyRect);
if (DEBUG_VIEWPORT_WINDOW) {
- Slog.i(LOG_TAG, "Bounds: " + mBounds);
+ Slog.i(LOG_TAG, "ViewportWindow bounds: " + mBounds);
+ Slog.i(LOG_TAG, "ViewportWindow dirty rect: " + mDirtyRect);
}
- canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
- mPaint.setAlpha(mAlpha);
- Path path = mBounds.getBoundaryPath();
- canvas.drawPath(path, mPaint);
-
- mSurface.unlockCanvasAndPost(canvas);
- t.show(mSurfaceControl);
- } else {
- t.hide(mSurfaceControl);
}
}
+
+ // Draw without holding WindowManagerGlobalLock.
+ if (alpha > 0) {
+ Canvas canvas = null;
+ try {
+ canvas = mSurface.lockCanvas(drawingRect);
+ } catch (IllegalArgumentException | OutOfResourcesException e) {
+ /* ignore */
+ }
+ if (canvas == null) {
+ return;
+ }
+ canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
+ mPaint.setAlpha(alpha);
+ canvas.drawPath(drawingBounds.getBoundaryPath(), mPaint);
+ mSurface.unlockCanvasAndPost(canvas);
+ t.show(mSurfaceControl);
+ } else {
+ t.hide(mSurfaceControl);
+ }
}
void releaseSurface() {
diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java
index 01158779c24f..5a7799e318c1 100644
--- a/services/core/java/com/android/server/wm/AsyncRotationController.java
+++ b/services/core/java/com/android/server/wm/AsyncRotationController.java
@@ -33,6 +33,7 @@ import android.view.animation.AnimationUtils;
import com.android.internal.R;
+import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.function.Consumer;
@@ -236,7 +237,15 @@ class AsyncRotationController extends FadeAnimationController implements Consume
* operation directly to avoid waiting until timeout.
*/
void updateTargetWindows() {
- if (mTransitionOp == OP_LEGACY || !mIsStartTransactionCommitted) return;
+ if (mTransitionOp == OP_LEGACY) return;
+ if (!mIsStartTransactionCommitted) {
+ if (mTimeoutRunnable == null && !mDisplayContent.hasTopFixedRotationLaunchingApp()
+ && !mDisplayContent.isRotationChanging() && !mDisplayContent.inTransition()) {
+ Slog.d(TAG, "Cancel for no change");
+ mDisplayContent.finishAsyncRotationIfPossible();
+ }
+ return;
+ }
for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
final Operation op = mTargetWindowTokens.valueAt(i);
if (op.mIsCompletionPending || op.mAction == Operation.ACTION_SEAMLESS) {
@@ -592,6 +601,16 @@ class AsyncRotationController extends FadeAnimationController implements Consume
return !mAlwaysWaitForStartTransaction && op.mAction != Operation.ACTION_SEAMLESS;
}
+ void dump(PrintWriter pw, String prefix) {
+ pw.println(prefix + "AsyncRotationController");
+ prefix += " ";
+ pw.println(prefix + "mTransitionOp=" + mTransitionOp);
+ pw.println(prefix + "mIsStartTransactionCommitted=" + mIsStartTransactionCommitted);
+ pw.println(prefix + "mIsSyncDrawRequested=" + mIsSyncDrawRequested);
+ pw.println(prefix + "mOriginalRotation=" + mOriginalRotation);
+ pw.println(prefix + "mTargetWindowTokens=" + mTargetWindowTokens);
+ }
+
/** The operation to control the rotation appearance associated with window token. */
private static class Operation {
@Retention(RetentionPolicy.SOURCE)
@@ -619,5 +638,10 @@ class AsyncRotationController extends FadeAnimationController implements Consume
Operation(@Action int action) {
mAction = action;
}
+
+ @Override
+ public String toString() {
+ return "Operation{a=" + mAction + " pending=" + mIsCompletionPending + '}';
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ef19eef22794..d288663ab2db 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3453,6 +3453,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
if (mFixedRotationLaunchingApp != null) {
setSeamlessTransitionForFixedRotation(controller.getCollectingTransition());
}
+ } else if (mAsyncRotationController != null && !isRotationChanging()) {
+ Slog.i(TAG, "Finish AsyncRotation for previous intermediate change");
+ finishAsyncRotationIfPossible();
}
return;
}
@@ -3621,6 +3624,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
if (mFixedRotationLaunchingApp != null) {
pw.println(" mFixedRotationLaunchingApp=" + mFixedRotationLaunchingApp);
}
+ if (mAsyncRotationController != null) {
+ mAsyncRotationController.dump(pw, prefix);
+ }
pw.println();
pw.print(prefix + "mHoldScreenWindow="); pw.print(mHoldScreenWindow);
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 65c5c9b35ab7..2ac3125de961 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -1468,6 +1468,17 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
mTargetDisplays.add(dc);
}
+ for (int i = 0; i < mTargets.size(); ++i) {
+ final DisplayArea da = mTargets.get(i).mContainer.asDisplayArea();
+ if (da == null) continue;
+ if (da.isVisibleRequested()) {
+ mController.mValidateDisplayVis.remove(da);
+ } else {
+ // In case something accidentally hides a displayarea and nothing shows it again.
+ mController.mValidateDisplayVis.add(da);
+ }
+ }
+
if (mOverrideOptions != null) {
info.setAnimationOptions(mOverrideOptions);
if (mOverrideOptions.getType() == ANIM_OPEN_CROSS_PROFILE_APPS) {
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index b05c6b4839e5..7169c2cfa0f6 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -150,6 +150,13 @@ class TransitionController {
final ArrayList<ActivityRecord> mValidateActivityCompat = new ArrayList<>();
/**
+ * List of display areas which were last sent as "closing"-type and haven't yet had a
+ * corresponding "opening"-type transition. A mismatch here is usually related to issues in
+ * keyguard unlock.
+ */
+ final ArrayList<DisplayArea> mValidateDisplayVis = new ArrayList<>();
+
+ /**
* Currently playing transitions (in the order they were started). When finished, records are
* removed from this list.
*/
@@ -922,6 +929,15 @@ class TransitionController {
ar.getSyncTransaction().setPosition(ar.getSurfaceControl(), tmpPos.x, tmpPos.y);
}
mValidateActivityCompat.clear();
+ for (int i = 0; i < mValidateDisplayVis.size(); ++i) {
+ final DisplayArea da = mValidateDisplayVis.get(i);
+ if (!da.isAttached() || da.getSurfaceControl() == null) continue;
+ if (da.isVisibleRequested()) {
+ Slog.e(TAG, "DisplayArea became visible outside of a transition: " + da);
+ da.getSyncTransaction().show(da.getSurfaceControl());
+ }
+ }
+ mValidateDisplayVis.clear();
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 06978a5338ea..c4506d59c138 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5664,6 +5664,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// TODO(b/233286785): Add sync support to wallpaper.
return false;
}
+ if (mActivityRecord != null && mViewVisibility != View.VISIBLE
+ && mWinAnimator.mAttrType != TYPE_BASE_APPLICATION
+ && mWinAnimator.mAttrType != TYPE_APPLICATION_STARTING) {
+ // Skip sync for invisible app windows which are not managed by activity lifecycle.
+ return false;
+ }
// In the WindowContainer implementation we immediately mark ready
// since a generic WindowContainer only needs to wait for its
// children to finish and is immediately ready from its own
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index 9c1d765fe0f9..9f65a33185b5 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -30,6 +30,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppGlobals;
import android.app.BroadcastOptions;
+import android.app.admin.BooleanPolicyValue;
import android.app.admin.DevicePolicyIdentifiers;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyState;
@@ -133,6 +134,67 @@ final class DevicePolicyEngine {
mEnforcingAdmins = new SparseArray<>();
}
+ private void maybeForceEnforcementRefreshLocked(@NonNull PolicyDefinition<?> policyDefinition) {
+ try {
+ if (shouldForceEnforcementRefresh(policyDefinition)) {
+ // This is okay because it's only true for user restrictions which are all <Boolean>
+ forceEnforcementRefreshLocked((PolicyDefinition<Boolean>) policyDefinition);
+ }
+ } catch (Throwable e) {
+ // Catch any possible exceptions just to be on the safe side
+ Log.e(TAG, "Exception throw during maybeForceEnforcementRefreshLocked", e);
+ }
+ }
+
+ private boolean shouldForceEnforcementRefresh(@NonNull PolicyDefinition<?> policyDefinition) {
+ // These are all "not nullable" but for the purposes of maximum safety for a lightly tested
+ // change we check here
+ if (policyDefinition == null) {
+ return false;
+ }
+ PolicyKey policyKey = policyDefinition.getPolicyKey();
+ if (policyKey == null) {
+ return false;
+ }
+
+ if (policyKey instanceof UserRestrictionPolicyKey) {
+ // b/307481299 We must force all user restrictions to re-sync local
+ // + global on each set/clear
+ return true;
+ }
+
+ return false;
+ }
+
+ private void forceEnforcementRefreshLocked(PolicyDefinition<Boolean> policyDefinition) {
+ Binder.withCleanCallingIdentity(() -> {
+ // Sync global state
+ PolicyValue<Boolean> globalValue = new BooleanPolicyValue(false);
+ try {
+ PolicyState<Boolean> policyState = getGlobalPolicyStateLocked(policyDefinition);
+ globalValue = policyState.getCurrentResolvedPolicy();
+ } catch (IllegalArgumentException e) {
+ // Expected for local-only policies
+ }
+
+ enforcePolicy(policyDefinition, globalValue, UserHandle.USER_ALL);
+
+ // Loop through each user and sync that user's state
+ for (UserInfo user : mUserManager.getUsers()) {
+ PolicyValue<Boolean> localValue = new BooleanPolicyValue(false);
+ try {
+ PolicyState<Boolean> localPolicyState = getLocalPolicyStateLocked(
+ policyDefinition, user.id);
+ localValue = localPolicyState.getCurrentResolvedPolicy();
+ } catch (IllegalArgumentException e) {
+ // Expected for global-only policies
+ }
+
+ enforcePolicy(policyDefinition, localValue, user.id);
+ }
+ });
+ }
+
/**
* Set the policy for the provided {@code policyDefinition} (see {@link PolicyDefinition}) and
* {@code enforcingAdmin} to the provided {@code value}.
@@ -174,6 +236,7 @@ final class DevicePolicyEngine {
// No need to notify admins as no new policy is actually enforced, we're just filling in
// the data structures.
if (!skipEnforcePolicy) {
+ maybeForceEnforcementRefreshLocked(policyDefinition);
if (policyChanged) {
onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId);
}
@@ -262,6 +325,7 @@ final class DevicePolicyEngine {
Objects.requireNonNull(enforcingAdmin);
synchronized (mLock) {
+ maybeForceEnforcementRefreshLocked(policyDefinition);
if (!hasLocalPolicyLocked(policyDefinition, userId)) {
return;
}
@@ -425,6 +489,7 @@ final class DevicePolicyEngine {
// No need to notify admins as no new policy is actually enforced, we're just filling in
// the data structures.
if (!skipEnforcePolicy) {
+ maybeForceEnforcementRefreshLocked(policyDefinition);
if (policyChanged) {
onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin);
}
@@ -474,6 +539,7 @@ final class DevicePolicyEngine {
PolicyState<V> policyState = getGlobalPolicyStateLocked(policyDefinition);
boolean policyChanged = policyState.removePolicy(enforcingAdmin);
+ maybeForceEnforcementRefreshLocked(policyDefinition);
if (policyChanged) {
onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin);
}
diff --git a/services/tests/servicestests/res/xml/user_100_v9.xml b/services/tests/servicestests/res/xml/user_100_v9.xml
new file mode 100644
index 000000000000..03c08ed40828
--- /dev/null
+++ b/services/tests/servicestests/res/xml/user_100_v9.xml
@@ -0,0 +1,20 @@
+<user id="100"
+ serialNumber="0"
+ flags="3091"
+ type="android.os.usertype.full.SYSTEM"
+ created="0"
+ lastLoggedIn="0"
+ lastLoggedInFingerprint="0"
+ profileBadge="0">
+ <restrictions no_oem_unlock="true" />
+ <device_policy_local_restrictions>
+ <restrictions_user user_id="0">
+ <restrictions no_camera="true" />
+ </restrictions_user>
+ <restrictions_user user_id="100">
+ <restrictions no_camera="true" />
+ <restrictions no_install_unknown_sources="true" />
+ </restrictions_user>
+ </device_policy_local_restrictions>
+ <ignorePrepareStorageErrors>false</ignorePrepareStorageErrors>
+</user> \ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
index 2273fcd22b38..429c58e768bf 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
@@ -43,27 +43,33 @@ import android.annotation.UserIdInt;
import android.app.PropertyInvalidatedCache;
import android.content.pm.UserInfo;
import android.content.pm.UserInfo.UserInfoFlag;
+import android.content.res.Resources;
import android.os.Looper;
import android.os.Parcel;
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
import android.text.TextUtils;
+import android.util.Xml;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.frameworks.servicestests.R;
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerService.UserData;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
+import java.nio.charset.StandardCharsets;
import java.util.List;
/**
@@ -76,6 +82,7 @@ import java.util.List;
@MediumTest
public class UserManagerServiceUserInfoTest {
private UserManagerService mUserManagerService;
+ private Resources mResources;
@Before
public void setup() {
@@ -95,6 +102,8 @@ public class UserManagerServiceUserInfoTest {
assertEquals("Multiple users so this test can't run.", 1, users.size());
assertEquals("Only user present isn't the system user.",
UserHandle.USER_SYSTEM, users.get(0).id);
+
+ mResources = InstrumentationRegistry.getTargetContext().getResources();
}
@Test
@@ -108,11 +117,51 @@ public class UserManagerServiceUserInfoTest {
byte[] bytes = baos.toByteArray();
UserData read = mUserManagerService.readUserLP(
- data.info.id, new ByteArrayInputStream(bytes));
+ data.info.id, new ByteArrayInputStream(bytes), 0);
assertUserInfoEquals(data.info, read.info, /* parcelCopy= */ false);
}
+ /** Tests that device policy restrictions are written/read properly. */
+ @Test
+ public void testWriteReadDevicePolicyUserRestrictions() throws Exception {
+ final String globalRestriction = UserManager.DISALLOW_FACTORY_RESET;
+ final String localRestriction = UserManager.DISALLOW_CONFIG_DATE_TIME;
+
+ UserData data = new UserData();
+ data.info = createUser(100, FLAG_FULL, "A type");
+
+ mUserManagerService.putUserInfo(data.info);
+
+ // Set a global and user restriction so they get written out to the user file.
+ setUserRestrictions(data.info.id, globalRestriction, localRestriction, true);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(baos);
+ mUserManagerService.writeUserLP(data, out);
+ byte[] bytes = baos.toByteArray();
+
+ // Clear the restrictions to see if they are properly read in from the user file.
+ setUserRestrictions(data.info.id, globalRestriction, localRestriction, false);
+
+ final int userVersion = 10;
+ //read the secondary and SYSTEM user file to fetch local/global device policy restrictions.
+ mUserManagerService.readUserLP(data.info.id, new ByteArrayInputStream(bytes),
+ userVersion);
+
+ assertTrue(mUserManagerService.hasUserRestrictionOnAnyUser(globalRestriction));
+ assertTrue(mUserManagerService.hasUserRestrictionOnAnyUser(localRestriction));
+ }
+
+ /** Sets a global and local restriction and verifies they were set properly **/
+ private void setUserRestrictions(int id, String global, String local, boolean enabled) {
+ mUserManagerService.setUserRestrictionInner(UserHandle.USER_ALL, global, enabled);
+ assertEquals(mUserManagerService.hasUserRestrictionOnAnyUser(global), enabled);
+
+ mUserManagerService.setUserRestrictionInner(id, local, enabled);
+ assertEquals(mUserManagerService.hasUserRestrictionOnAnyUser(local), enabled);
+ }
+
@Test
public void testParcelUnparcelUserInfo() throws Exception {
UserInfo info = createUser();
@@ -250,6 +299,45 @@ public class UserManagerServiceUserInfoTest {
assertTrue(mUserManagerService.isUserOfType(106, USER_TYPE_FULL_DEMO));
}
+ /** Tests readUserLP upgrading from version 9 to 10+. */
+ @Test
+ public void testUserRestrictionsUpgradeFromV9() throws Exception {
+ final String[] localRestrictions = new String[] {
+ UserManager.DISALLOW_CAMERA,
+ UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+ };
+
+ final int userId = 100;
+ UserData data = new UserData();
+ data.info = createUser(userId, FLAG_FULL, "A type");
+
+ mUserManagerService.putUserInfo(data.info);
+
+ for (String restriction : localRestrictions) {
+ assertFalse(mUserManagerService.hasBaseUserRestriction(restriction, userId));
+ assertFalse(mUserManagerService.hasUserRestriction(restriction, userId));
+ }
+
+ // Convert the xml resource to the system storage xml format.
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream os = new DataOutputStream(baos);
+ XmlPullParser in = mResources.getXml(R.xml.user_100_v9);
+ XmlSerializer out = Xml.newBinarySerializer();
+ out.setOutput(os, StandardCharsets.UTF_8.name());
+ Xml.copy(in, out);
+ byte[] userBytes = baos.toByteArray();
+ baos.reset();
+
+ final int userVersion = 9;
+ mUserManagerService.readUserLP(data.info.id, new ByteArrayInputStream(userBytes),
+ userVersion);
+
+ for (String restriction : localRestrictions) {
+ assertFalse(mUserManagerService.hasBaseUserRestriction(restriction, userId));
+ assertTrue(mUserManagerService.hasUserRestriction(restriction, userId));
+ }
+ }
+
/** Creates a UserInfo with the given flags and userType. */
private UserInfo createUser(@UserIdInt int userId, @UserInfoFlag int flags, String userType) {
return new UserInfo(userId, "A Name", "A path", flags, userType);
diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java
index 3102639ff148..29e3d58696e6 100644
--- a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java
@@ -116,7 +116,7 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
testServiceDefaultValue_On(ServiceType.NULL);
}
- @Suppress
+ @Suppress // TODO: b/317823111 - Remove once test fixed.
@SmallTest
public void testGetBatterySaverPolicy_PolicyVibration_DefaultValueCorrect() {
testServiceDefaultValue_On(ServiceType.VIBRATION);
@@ -202,7 +202,7 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
testServiceDefaultValue_On(ServiceType.QUICK_DOZE);
}
- @Suppress
+ @Suppress // TODO: b/317823111 - Remove once test fixed.
@SmallTest
public void testUpdateConstants_getCorrectData() {
mBatterySaverPolicy.updateConstantsLocked(BATTERY_SAVER_CONSTANTS, "");
@@ -302,6 +302,7 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
}
}
+ @Suppress // TODO: b/317823111 - Remove once test fixed.
public void testSetPolicyLevel_Adaptive() {
mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_ADAPTIVE);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 86d2b2fc6b56..620e362c86b8 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -865,13 +865,18 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
+ return generateNotificationRecord(channel, 1, userId);
+ }
+
+ private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
+ int userId) {
if (channel == null) {
channel = mTestNotificationChannel;
}
Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
.setContentTitle("foo")
.setSmallIcon(android.R.drawable.sym_def_app_icon);
- StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
+ StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0,
nb.build(), new UserHandle(userId), null, 0);
return new NotificationRecord(mContext, sbn, channel);
}
@@ -10795,6 +10800,51 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testUngroupingAutoSummary_differentUsers() throws Exception {
+ NotificationRecord nr0 =
+ generateNotificationRecord(mTestNotificationChannel, 0, USER_SYSTEM);
+ NotificationRecord nr1 =
+ generateNotificationRecord(mTestNotificationChannel, 1, USER_SYSTEM);
+
+ // add notifications + summary for USER_SYSTEM
+ mService.addNotification(nr0);
+ mService.addNotification(nr1);
+ mService.addNotification(mService.createAutoGroupSummary(nr1.getUserId(),
+ nr1.getSbn().getPackageName(), nr1.getKey(), GroupHelper.BASE_FLAGS));
+
+ // add notifications + summary for USER_ALL
+ NotificationRecord nr0_all =
+ generateNotificationRecord(mTestNotificationChannel, 2, UserHandle.USER_ALL);
+ NotificationRecord nr1_all =
+ generateNotificationRecord(mTestNotificationChannel, 3, UserHandle.USER_ALL);
+
+ mService.addNotification(nr0_all);
+ mService.addNotification(nr1_all);
+ mService.addNotification(mService.createAutoGroupSummary(nr0_all.getUserId(),
+ nr0_all.getSbn().getPackageName(), nr0_all.getKey(), GroupHelper.BASE_FLAGS));
+
+ // cancel both children for USER_ALL
+ mBinderService.cancelNotificationWithTag(PKG, PKG, nr0_all.getSbn().getTag(),
+ nr0_all.getSbn().getId(), UserHandle.USER_ALL);
+ mBinderService.cancelNotificationWithTag(PKG, PKG, nr1_all.getSbn().getTag(),
+ nr1_all.getSbn().getId(), UserHandle.USER_ALL);
+ waitForIdle();
+
+ // group helper would send 'remove summary' event
+ mService.clearAutogroupSummaryLocked(UserHandle.USER_ALL,
+ nr0_all.getSbn().getPackageName());
+ waitForIdle();
+
+ // make sure the right summary was removed
+ assertThat(mService.getNotificationCount(nr0_all.getSbn().getPackageName(),
+ UserHandle.USER_ALL, 0, null)).isEqualTo(0);
+
+ // the USER_SYSTEM notifications + summary were not removed
+ assertThat(mService.getNotificationCount(nr0.getSbn().getPackageName(),
+ USER_SYSTEM, 0, null)).isEqualTo(3);
+ }
+
+ @Test
public void testStrongAuthTracker_isInLockDownMode() {
mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 340b591e4086..b2fb891dadb3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -2073,6 +2073,17 @@ public class DisplayContentTests extends WindowTestsBase {
assertNotEquals(testPlayer.mLastReady.getChange(dcToken).getEndRotation(),
testPlayer.mLastReady.getChange(dcToken).getStartRotation());
testPlayer.finish();
+
+ // The AsyncRotationController should only exist if there is an ongoing rotation change.
+ dc.finishAsyncRotationIfPossible();
+ dc.setLastHasContent();
+ doReturn(dr.getRotation() + 1).when(dr).rotationForOrientation(anyInt(), anyInt());
+ dr.updateRotationUnchecked(true /* forceUpdate */);
+ assertNotNull(dc.getAsyncRotationController());
+ doReturn(dr.getRotation() - 1).when(dr).rotationForOrientation(anyInt(), anyInt());
+ dr.updateRotationUnchecked(true /* forceUpdate */);
+ assertNull("Cancel AsyncRotationController for the intermediate rotation changes 0->1->0",
+ dc.getAsyncRotationController());
}
@Test