diff options
25 files changed, 478 insertions, 124 deletions
diff --git a/apct-tests/perftests/packagemanager/AndroidTest.xml b/apct-tests/perftests/packagemanager/AndroidTest.xml index c9d45a6bda74..db938e4373a3 100644 --- a/apct-tests/perftests/packagemanager/AndroidTest.xml +++ b/apct-tests/perftests/packagemanager/AndroidTest.xml @@ -76,11 +76,6 @@ <option name="test-file-name" value="QueriesAll49.apk"/> </target_preparer> - <test class="com.android.tradefed.testtype.AndroidJUnitTest"> - <option name="package" value="com.android.perftests.packagemanager"/> - <option name="hidden-api-checks" value="false"/> - </test> - <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> <option name="directory-keys" value="/data/local/PackageManagerPerfTests"/> <option name="collect-on-run-ended-only" value="true"/> diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 54fb4e72a79c..e20770cf20be 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2982,6 +2982,16 @@ public abstract class PackageManager { /** * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature}: This device is capable of launching apps in automotive display + * compatibility mode. + * @hide + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_CAR_DISPLAY_COMPATIBILITY = + "android.software.car.display_compatibility"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature(String, int)}: If this feature is supported, the device supports * {@link android.security.identity.IdentityCredentialStore} implemented in secure hardware * at the given feature version. diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index 3cb5c60259eb..2b84b25b92e2 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -424,6 +424,8 @@ public class ZygoteProcess { throw new ZygoteStartFailedEx("Embedded newlines not allowed"); } else if (arg.indexOf('\r') >= 0) { throw new ZygoteStartFailedEx("Embedded carriage returns not allowed"); + } else if (arg.indexOf('\u0000') >= 0) { + throw new ZygoteStartFailedEx("Embedded nulls not allowed"); } } @@ -959,6 +961,14 @@ public class ZygoteProcess { return true; } + for (/* NonNull */ String s : mApiDenylistExemptions) { + // indexOf() is intrinsified and faster than contains(). + if (s.indexOf('\n') >= 0 || s.indexOf('\r') >= 0 || s.indexOf('\u0000') >= 0) { + Slog.e(LOG_TAG, "Failed to set API denylist exemptions: Bad character"); + mApiDenylistExemptions = Collections.emptyList(); + return false; + } + } try { state.mZygoteOutputWriter.write(Integer.toString(mApiDenylistExemptions.size() + 1)); state.mZygoteOutputWriter.newLine(); diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt index 2883210805d3..2359f6ad3b43 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt @@ -18,16 +18,10 @@ package com.android.systemui.media.controls.ui import android.content.Context import android.content.res.Configuration -import android.database.ContentObserver -import android.net.Uri -import android.os.Handler -import android.os.UserHandle -import android.provider.Settings import android.view.View import android.view.ViewGroup import androidx.annotation.VisibleForTesting import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.media.dagger.MediaModule.KEYGUARD import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.StatusBarState @@ -36,7 +30,6 @@ import com.android.systemui.statusbar.notification.stack.MediaContainerView import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.LargeScreenUtils -import com.android.systemui.util.settings.SecureSettings import javax.inject.Inject import javax.inject.Named @@ -52,8 +45,6 @@ constructor( private val bypassController: KeyguardBypassController, private val statusBarStateController: SysuiStatusBarStateController, private val context: Context, - private val secureSettings: SecureSettings, - @Main private val handler: Handler, configurationController: ConfigurationController, ) { @@ -77,26 +68,6 @@ constructor( } ) - val settingsObserver: ContentObserver = - object : ContentObserver(handler) { - override fun onChange(selfChange: Boolean, uri: Uri?) { - if (uri == lockScreenMediaPlayerUri) { - allowMediaPlayerOnLockScreen = - secureSettings.getBoolForUser( - Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, - true, - UserHandle.USER_CURRENT - ) - refreshMediaPosition() - } - } - } - secureSettings.registerContentObserverForUser( - Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, - settingsObserver, - UserHandle.USER_ALL - ) - // First let's set the desired state that we want for this host mediaHost.expansion = MediaHostState.EXPANDED mediaHost.showsOnlyActiveMedia = true @@ -142,16 +113,6 @@ constructor( private set private var splitShadeContainer: ViewGroup? = null - /** Track the media player setting status on lock screen. */ - private var allowMediaPlayerOnLockScreen: Boolean = - secureSettings.getBoolForUser( - Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, - true, - UserHandle.USER_CURRENT - ) - private val lockScreenMediaPlayerUri = - secureSettings.getUriFor(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN) - /** * Attaches media container in single pane mode, situated at the top of the notifications list */ @@ -211,7 +172,6 @@ constructor( mediaHost.visible && !bypassController.bypassEnabled && keyguardOrUserSwitcher && - allowMediaPlayerOnLockScreen && shouldBeVisibleForSplitShade() if (visible) { showMediaPlayer() diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt index c1c757e424dc..2db9fc90d1f8 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt @@ -104,7 +104,7 @@ constructor( ) { /** Track the media player setting status on lock screen. */ - private var allowMediaPlayerOnLockScreen: Boolean = true + private var allowMediaPlayerOnLockScreen: Boolean = getMediaLockScreenSetting() private val lockScreenMediaPlayerUri = secureSettings.getUriFor(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN) @@ -461,6 +461,7 @@ constructor( mediaCarouselController.logSmartspaceImpression(qsExpanded) } updateUserVisibility() + mediaCarouselController.updateHostVisibility() } override fun onDozeAmountChanged(linear: Float, eased: Float) { @@ -533,7 +534,6 @@ constructor( mediaCarouselController.updateHostVisibility = { mediaHosts.forEach { it?.updateViewVisibility() } } - panelEventsEvents.addShadeStateEventsListener( object : ShadeStateEventsListener { override fun onExpandImmediateChanged(isExpandImmediateEnabled: Boolean) { @@ -547,12 +547,8 @@ constructor( object : ContentObserver(handler) { override fun onChange(selfChange: Boolean, uri: Uri?) { if (uri == lockScreenMediaPlayerUri) { - allowMediaPlayerOnLockScreen = - secureSettings.getBoolForUser( - Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, - true, - UserHandle.USER_CURRENT - ) + allowMediaPlayerOnLockScreen = getMediaLockScreenSetting() + mediaCarouselController.updateHostVisibility() } } } @@ -563,6 +559,14 @@ constructor( ) } + private fun getMediaLockScreenSetting(): Boolean { + return secureSettings.getBoolForUser( + Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, + true, + UserHandle.USER_CURRENT + ) + } + private fun updateConfiguration() { distanceForFullShadeTransition = context.resources.getDimensionPixelSize( @@ -602,6 +606,13 @@ constructor( mediaCarouselController.closeGuts() } + /** Return true if the carousel should be hidden because lockscreen is currently visible */ + fun isLockedAndHidden(): Boolean { + return !allowMediaPlayerOnLockScreen && + (statusbarState == StatusBarState.SHADE_LOCKED || + statusbarState == StatusBarState.KEYGUARD) + } + private fun createUniqueObjectHost(): UniqueObjectHostView { val viewHost = UniqueObjectHostView(context) viewHost.addOnAttachStateChangeListener( diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt index 631a0b8471b8..13cfb0a056d3 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt @@ -199,7 +199,9 @@ constructor( */ fun updateViewVisibility() { state.visible = - if (showsOnlyActiveMedia) { + if (mediaHierarchyManager.isLockedAndHidden()) { + false + } else if (showsOnlyActiveMedia) { mediaDataManager.hasActiveMediaOrRecommendation() } else { mediaDataManager.hasAnyMediaOrRecommendation() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index d92d11b18d74..a8bd4e4a0c66 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -40,6 +40,7 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.os.Trace; +import android.os.UserHandle; import android.service.notification.StatusBarNotification; import android.util.ArraySet; import android.util.AttributeSet; @@ -377,7 +378,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private boolean mUseIncreasedHeadsUpHeight; private float mTranslationWhenRemoved; private boolean mWasChildInGroupWhenRemoved; - private NotificationInlineImageResolver mImageResolver; + private final NotificationInlineImageResolver mImageResolver; @Nullable private OnExpansionChangedListener mExpansionChangedListener; @Nullable @@ -1681,13 +1682,41 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } /** - * Constructs an ExpandableNotificationRow. - * @param context context passed to image resolver + * Constructs an ExpandableNotificationRow. Used by layout inflation. + * + * @param context passed to image resolver * @param attrs attributes used to initialize parent view */ public ExpandableNotificationRow(Context context, AttributeSet attrs) { - super(context, attrs); - mImageResolver = new NotificationInlineImageResolver(context, + this(context, attrs, context); + Log.wtf(TAG, "This constructor shouldn't be called"); + } + + /** + * Constructs an ExpandableNotificationRow. Used by layout inflation (with a custom {@code + * AsyncLayoutFactory} in {@link RowInflaterTask}. + * + * @param context context context of the view + * @param attrs attributes used to initialize parent view + * @param entry notification that the row will be associated to (determines the user for the + * ImageResolver) + */ + public ExpandableNotificationRow(Context context, AttributeSet attrs, NotificationEntry entry) { + this(context, attrs, userContextForEntry(context, entry)); + } + + private static Context userContextForEntry(Context base, NotificationEntry entry) { + if (base.getUserId() == entry.getSbn().getNormalizedUserId()) { + return base; + } + return base.createContextAsUser( + UserHandle.of(entry.getSbn().getNormalizedUserId()), /* flags= */ 0); + } + + private ExpandableNotificationRow(Context sysUiContext, AttributeSet attrs, + Context userContext) { + super(sysUiContext, attrs); + mImageResolver = new NotificationInlineImageResolver(userContext, new NotificationInlineImageCache()); float radius = getResources().getDimension(R.dimen.notification_corner_radius_small); mSmallRoundness = radius / getMaxRadius(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java index c620f448b3b7..3e932aa616b8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java @@ -66,7 +66,7 @@ public class NotificationInlineImageResolver implements ImageResolver { * @param imageCache The implementation of internal cache. */ public NotificationInlineImageResolver(Context context, ImageCache imageCache) { - mContext = context.getApplicationContext(); + mContext = context; mImageCache = imageCache; if (mImageCache != null) { @@ -76,6 +76,11 @@ public class NotificationInlineImageResolver implements ImageResolver { updateMaxImageSizes(); } + @VisibleForTesting + public Context getContext() { + return mContext; + } + /** * Check if this resolver has its internal cache implementation. * @return True if has its internal cache, false otherwise. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java index 6feffe654630..b2fe1d82945b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java @@ -17,10 +17,15 @@ package com.android.systemui.statusbar.notification.row; import android.content.Context; +import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import androidx.asynclayoutinflater.view.AsyncLayoutFactory; import androidx.asynclayoutinflater.view.AsyncLayoutInflater; import com.android.systemui.R; @@ -55,12 +60,39 @@ public class RowInflaterTask implements InflationTask, AsyncLayoutInflater.OnInf mInflateOrigin = new Throwable("inflate requested here"); } mListener = listener; - AsyncLayoutInflater inflater = new AsyncLayoutInflater(context); + AsyncLayoutInflater inflater = new AsyncLayoutInflater(context, + new RowAsyncLayoutInflater(entry)); mEntry = entry; entry.setInflationTask(this); inflater.inflate(R.layout.status_bar_notification_row, parent, this); } + @VisibleForTesting + static class RowAsyncLayoutInflater implements AsyncLayoutFactory { + private final NotificationEntry mEntry; + + RowAsyncLayoutInflater(NotificationEntry entry) { + mEntry = entry; + } + + @Nullable + @Override + public View onCreateView(@Nullable View parent, @NonNull String name, + @NonNull Context context, @NonNull AttributeSet attrs) { + if (name.equals(ExpandableNotificationRow.class.getName())) { + return new ExpandableNotificationRow(context, attrs, mEntry); + } + return null; + } + + @Nullable + @Override + public View onCreateView(@NonNull String name, @NonNull Context context, + @NonNull AttributeSet attrs) { + return null; + } + } + @Override public void abort() { mCancelled = true; diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt index 91b0245be8d3..c1cf7e07aee2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/KeyguardMediaControllerTest.kt @@ -16,7 +16,6 @@ package com.android.systemui.media.controls.ui -import android.provider.Settings import android.test.suitebuilder.annotation.SmallTest import android.testing.AndroidTestingRunner import android.testing.TestableLooper @@ -32,8 +31,6 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.animation.UniqueObjectHostView import com.android.systemui.util.mockito.whenever -import com.android.systemui.util.settings.FakeSettings -import com.android.systemui.utils.os.FakeHandler import com.google.common.truth.Truth.assertThat import junit.framework.Assert.assertTrue import org.junit.Before @@ -60,10 +57,7 @@ class KeyguardMediaControllerTest : SysuiTestCase() { private val mediaContainerView: MediaContainerView = MediaContainerView(context, null) private val hostView = UniqueObjectHostView(context) - private val settings = FakeSettings() private lateinit var keyguardMediaController: KeyguardMediaController - private lateinit var testableLooper: TestableLooper - private lateinit var fakeHandler: FakeHandler private lateinit var statusBarStateListener: StatusBarStateController.StateListener @Before @@ -79,16 +73,12 @@ class KeyguardMediaControllerTest : SysuiTestCase() { whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) whenever(mediaHost.hostView).thenReturn(hostView) hostView.layoutParams = FrameLayout.LayoutParams(100, 100) - testableLooper = TestableLooper.get(this) - fakeHandler = FakeHandler(testableLooper.looper) keyguardMediaController = KeyguardMediaController( mediaHost, bypassController, statusBarStateController, context, - settings, - fakeHandler, configurationController, ) keyguardMediaController.attachSinglePaneContainer(mediaContainerView) @@ -118,24 +108,6 @@ class KeyguardMediaControllerTest : SysuiTestCase() { } @Test - fun testHiddenOnKeyguard_whenMediaOnLockScreenDisabled() { - settings.putInt(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, 0) - - keyguardMediaController.refreshMediaPosition() - - assertThat(mediaContainerView.visibility).isEqualTo(GONE) - } - - @Test - fun testAvailableOnKeyguard_whenMediaOnLockScreenEnabled() { - settings.putInt(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, 1) - - keyguardMediaController.refreshMediaPosition() - - assertThat(mediaContainerView.visibility).isEqualTo(VISIBLE) - } - - @Test fun testActivatesSplitShadeContainerInSplitShadeMode() { val splitShadeContainer = FrameLayout(context) keyguardMediaController.attachSplitShadeContainer(splitShadeContainer) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt index 2ce236d4ba89..69bf97f6545f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt @@ -124,6 +124,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() { verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture()) verify(statusBarStateController).addCallback(statusBarCallback.capture()) verify(dreamOverlayStateController).addCallback(dreamOverlayCallback.capture()) + whenever(mediaCarouselController.updateHostVisibility).thenReturn({}) setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN, LOCKSCREEN_TOP) setupHost(qsHost, MediaHierarchyManager.LOCATION_QS, QS_TOP) setupHost(qqsHost, MediaHierarchyManager.LOCATION_QQS, QQS_TOP) @@ -485,6 +486,55 @@ class MediaHierarchyManagerTest : SysuiTestCase() { assertThat(mediaCarouselScrollHandler.visibleToUser).isFalse() } + @Test + fun keyguardState_allowedOnLockscreen_updateVisibility() { + settings.putBool(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, true) + clearInvocations(mediaCarouselController) + + statusBarCallback.value.onStatePreChange(StatusBarState.SHADE, StatusBarState.KEYGUARD) + statusBarCallback.value.onStateChanged(StatusBarState.KEYGUARD) + + verify(mediaCarouselController).updateHostVisibility + assertThat(mediaHierarchyManager.isLockedAndHidden()).isFalse() + } + + @Test + fun keyguardState_notAllowedOnLockscreen_updateVisibility() { + settings.putBool(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, false) + clearInvocations(mediaCarouselController) + + statusBarCallback.value.onStatePreChange(StatusBarState.SHADE, StatusBarState.KEYGUARD) + statusBarCallback.value.onStateChanged(StatusBarState.KEYGUARD) + + verify(mediaCarouselController).updateHostVisibility + assertThat(mediaHierarchyManager.isLockedAndHidden()).isTrue() + } + + @Test + fun keyguardGone_updateVisibility() { + settings.putBool(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, false) + clearInvocations(mediaCarouselController) + + statusBarCallback.value.onStatePreChange(StatusBarState.KEYGUARD, StatusBarState.SHADE) + statusBarCallback.value.onStateChanged(StatusBarState.SHADE) + + verify(mediaCarouselController).updateHostVisibility + assertThat(mediaHierarchyManager.isLockedAndHidden()).isFalse() + } + + @Test + fun lockscreenSettingChanged_updateVisibility() { + settings.putBool(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, true) + statusBarCallback.value.onStatePreChange(StatusBarState.SHADE, StatusBarState.KEYGUARD) + statusBarCallback.value.onStateChanged(StatusBarState.KEYGUARD) + clearInvocations(mediaCarouselController) + + settings.putBool(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, false) + + verify(mediaCarouselController).updateHostVisibility + assertThat(mediaHierarchyManager.isLockedAndHidden()).isTrue() + } + private fun enableSplitShade() { context .getOrCreateTestableResources() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index ac8b42afd4b2..15dffb0726a9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -20,6 +20,8 @@ import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking; import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL; +import static com.android.systemui.statusbar.notification.row.NotificationTestHelper.PKG; +import static com.android.systemui.statusbar.notification.row.NotificationTestHelper.USER_HANDLE; import static com.google.common.truth.Truth.assertThat; @@ -41,10 +43,12 @@ import static org.mockito.Mockito.when; import android.app.Notification; import android.app.NotificationChannel; +import android.content.Context; import android.graphics.Color; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.Drawable; +import android.os.UserHandle; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; @@ -57,6 +61,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.internal.widget.CachingIconView; import com.android.systemui.SysuiTestCase; +import com.android.systemui.SysuiTestableContext; import com.android.systemui.flags.FakeFeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; @@ -833,6 +838,26 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { assertThat(row.isDrawingAppearAnimation()).isFalse(); } + @Test + public void imageResolver_sameNotificationUser_usesContext() throws Exception { + ExpandableNotificationRow row = mNotificationTestHelper.createRow(PKG, + USER_HANDLE.getUid(1234), USER_HANDLE); + + assertThat(row.getImageResolver().getContext()).isSameInstanceAs(mContext); + } + + @Test + public void imageResolver_differentNotificationUser_createsUserContext() throws Exception { + UserHandle user = new UserHandle(33); + Context userContext = new SysuiTestableContext(mContext); + mContext.prepareCreateContextAsUser(user, userContext); + + ExpandableNotificationRow row = mNotificationTestHelper.createRow(PKG, + user.getUid(1234), user); + + assertThat(row.getImageResolver().getContext()).isSameInstanceAs(userContext); + } + private void setDrawableIconsInImageView(CachingIconView icon, Drawable iconDrawable, Drawable rightIconDrawable) { ImageView iconView = mock(ImageView.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java index 5e090ce42bbe..3e3a2f57109a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java @@ -574,7 +574,8 @@ public class NotificationTestHelper { mFeatureFlags.setDefault(Flags.IMPROVED_HUN_ANIMATIONS); LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( - mContext.LAYOUT_INFLATER_SERVICE); + Context.LAYOUT_INFLATER_SERVICE); + inflater.setFactory2(new RowInflaterTask.RowAsyncLayoutInflater(entry)); mRow = (ExpandableNotificationRow) inflater.inflate( R.layout.status_bar_notification_row, null /* root */, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java index 5ff57aad9f5d..aa58b89f4676 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestableContext.java @@ -14,6 +14,7 @@ package com.android.systemui; +import android.annotation.NonNull; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -29,12 +30,15 @@ import android.view.Display; import com.android.internal.annotations.GuardedBy; +import java.util.HashMap; +import java.util.Map; import java.util.Set; public class SysuiTestableContext extends TestableContext { @GuardedBy("mRegisteredReceivers") private final Set<BroadcastReceiver> mRegisteredReceivers = new ArraySet<>(); + private final Map<UserHandle, Context> mContextForUser = new HashMap<>(); public SysuiTestableContext(Context base) { super(base); @@ -152,4 +156,22 @@ public class SysuiTestableContext extends TestableContext { } super.unregisterReceiver(receiver); } + + /** + * Sets a Context object that will be returned as the result of {@link #createContextAsUser} + * for a specific {@code user}. + */ + public void prepareCreateContextAsUser(UserHandle user, Context context) { + mContextForUser.put(user, context); + } + + @Override + @NonNull + public Context createContextAsUser(UserHandle user, int flags) { + Context userContext = mContextForUser.get(user); + if (userContext != null) { + return userContext; + } + return super.createContextAsUser(user, flags); + } } diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 531227947ba0..7bb7c4a81a7d 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -2398,10 +2398,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub userState.mComponentNameToServiceMap; boolean isUnlockingOrUnlocked = mUmi.isUserUnlockingOrUnlocked(userState.mUserId); + // Store the list of installed services. + mTempComponentNameSet.clear(); for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) { AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i); ComponentName componentName = ComponentName.unflattenFromString( installedService.getId()); + mTempComponentNameSet.add(componentName); AccessibilityServiceConnection service = componentNameToServiceMap.get(componentName); @@ -2461,6 +2464,25 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub audioManager.setAccessibilityServiceUids(mTempIntArray); } mActivityTaskManagerService.setAccessibilityServiceUids(mTempIntArray); + // If any services have been removed, remove them from the enabled list and the touch + // exploration granted list. + boolean anyServiceRemoved = + userState.mEnabledServices.removeIf((comp) -> !mTempComponentNameSet.contains(comp)) + || userState.mTouchExplorationGrantedServices.removeIf( + (comp) -> !mTempComponentNameSet.contains(comp)); + if (anyServiceRemoved) { + // Update the enabled services setting. + persistComponentNamesToSettingLocked( + Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, + userState.mEnabledServices, + userState.mUserId); + // Update the touch exploration granted services setting. + persistComponentNamesToSettingLocked( + Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES, + userState.mTouchExplorationGrantedServices, + userState.mUserId); + } + mTempComponentNameSet.clear(); updateAccessibilityEnabledSettingLocked(userState); } diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 63a607c8d0d4..7be2dea3c2f6 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -32,8 +32,10 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManagerInternal; import android.content.ComponentName; +import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.graphics.Rect; import android.metrics.LogMaker; @@ -250,6 +252,31 @@ final class AutofillManagerServiceImpl @Override // from PerUserSystemService protected ServiceInfo newServiceInfoLocked(@NonNull ComponentName serviceComponent) throws NameNotFoundException { + final List<ResolveInfo> resolveInfos = + getContext().getPackageManager().queryIntentServicesAsUser( + new Intent(AutofillService.SERVICE_INTERFACE), + // The MATCH_INSTANT flag is added because curret autofill CTS module is + // defined in one apk, which makes the test autofill service installed in a + // instant app when the CTS tests are running in instant app mode. + // TODO: Remove MATCH_INSTANT flag after completing refactoring the CTS module + // to make the test autofill service a separate apk. + PackageManager.GET_META_DATA | PackageManager.MATCH_INSTANT, + mUserId); + boolean serviceHasAutofillIntentFilter = false; + for (ResolveInfo resolveInfo : resolveInfos) { + final ServiceInfo serviceInfo = resolveInfo.serviceInfo; + if (serviceInfo.getComponentName().equals(serviceComponent)) { + serviceHasAutofillIntentFilter = true; + break; + } + } + if (!serviceHasAutofillIntentFilter) { + Slog.w(TAG, + "Autofill service from '" + serviceComponent.getPackageName() + "' does" + + "not have intent filter " + AutofillService.SERVICE_INTERFACE); + throw new SecurityException("Service does not declare intent filter " + + AutofillService.SERVICE_INTERFACE); + } mInfo = new AutofillServiceInfo(getContext(), serviceComponent, mUserId); return mInfo.getServiceInfo(); } diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index 0c6d053d4f3f..a3f66655795e 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -84,9 +84,7 @@ import android.os.ParcelFileDescriptor; import android.os.PowerWhitelistManager; import android.os.RemoteCallbackList; import android.os.RemoteException; -import android.os.ResultReceiver; import android.os.ServiceManager; -import android.os.ShellCallback; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; @@ -951,13 +949,14 @@ public class CompanionDeviceManagerService extends SystemService { } @Override - public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, - String[] args, ShellCallback callback, ResultReceiver resultReceiver) - throws RemoteException { - new CompanionDeviceShellCommand(CompanionDeviceManagerService.this, mAssociationStore, - mDevicePresenceMonitor, mTransportManager, mSystemDataTransferProcessor, - mAssociationRequestsProcessor) - .exec(this, in, out, err, args, callback, resultReceiver); + public int handleShellCommand(@NonNull ParcelFileDescriptor in, + @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, + @NonNull String[] args) { + return new CompanionDeviceShellCommand(CompanionDeviceManagerService.this, + mAssociationStore, mDevicePresenceMonitor, mTransportManager, + mSystemDataTransferProcessor, mAssociationRequestsProcessor) + .exec(this, in.getFileDescriptor(), out.getFileDescriptor(), + err.getFileDescriptor(), args); } @Override diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index b322c553211c..3603cf9e185f 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -3625,6 +3625,11 @@ public class AccountManagerService // Strip auth token from result. result.remove(AccountManager.KEY_AUTHTOKEN); + if (!checkKeyIntent(Binder.getCallingUid(), result)) { + onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, + "invalid intent in bundle returned"); + return; + } if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, @@ -5214,6 +5219,11 @@ public class AccountManagerService } else { if (mStripAuthTokenFromResult) { result.remove(AccountManager.KEY_AUTHTOKEN); + if (!checkKeyIntent(Binder.getCallingUid(), result)) { + onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, + "invalid intent in bundle returned"); + return; + } } if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, getClass().getSimpleName() diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index b3c11012b91b..9913dd6f0dbe 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -3105,8 +3105,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return false; } if (doAnimation) { - mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false); - if (!isAnimating(TRANSITION | PARENTS)) { + // If a hide animation is applied, then let onAnimationFinished + // -> checkPolicyVisibilityChange hide the window. Otherwise make doAnimation false + // to commit invisible immediately. + if (!mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false /* isEntrance */)) { doAnimation = false; } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 73292e2c3d5a..8c9596c8549e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -3392,6 +3392,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (shouldMigrateToDevicePolicyEngine()) { migratePoliciesToDevicePolicyEngine(); } + + maybeMigratePoliciesPostUpgradeToDevicePolicyEngineLocked(); } maybeStartSecurityLogMonitorOnActivityManagerReady(); break; @@ -13496,27 +13498,47 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { CallerIdentity caller, EnforcingAdmin admin, String key, boolean enabled, boolean parent) { synchronized (getLockObject()) { + + int ownerType; if (isDeviceOwner(caller)) { - if (UserRestrictionsUtils.isGlobal(OWNER_TYPE_DEVICE_OWNER, key)) { - setGlobalUserRestrictionInternal(admin, key, enabled); - } else { - setLocalUserRestrictionInternal(admin, key, enabled, caller.getUserId()); - } + ownerType = OWNER_TYPE_DEVICE_OWNER; + } else if (isProfileOwnerOfOrganizationOwnedDevice(caller)) { + ownerType = OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE; } else if (isProfileOwner(caller)) { - if (UserRestrictionsUtils.isGlobal(OWNER_TYPE_PROFILE_OWNER, key) - || (parent && isProfileOwnerOfOrganizationOwnedDevice(caller) - && UserRestrictionsUtils.isGlobal( - OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE, key))) { - setGlobalUserRestrictionInternal(admin, key, enabled); - } else { - int affectedUserId = parent - ? getProfileParentId(caller.getUserId()) : caller.getUserId(); - setLocalUserRestrictionInternal(admin, key, enabled, affectedUserId); - } + ownerType = OWNER_TYPE_PROFILE_OWNER; } else { throw new IllegalStateException("Non-DO/Non-PO cannot set restriction " + key + " while targetSdkVersion is less than UPSIDE_DOWN_CAKE"); } + setBackwardCompatibleUserRestrictionLocked(ownerType, admin, caller.getUserId(), key, + enabled, parent); + } + } + + private void setBackwardCompatibleUserRestrictionLocked( + int ownerType, EnforcingAdmin admin, int userId, String key, boolean enabled, + boolean parent) { + if (ownerType == OWNER_TYPE_DEVICE_OWNER) { + if (UserRestrictionsUtils.isGlobal(OWNER_TYPE_DEVICE_OWNER, key)) { + setGlobalUserRestrictionInternal(admin, key, enabled); + } else { + setLocalUserRestrictionInternal(admin, key, enabled, userId); + } + } else if (ownerType == OWNER_TYPE_PROFILE_OWNER + || ownerType == OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE) { + if (UserRestrictionsUtils.isGlobal(OWNER_TYPE_PROFILE_OWNER, key) + || (parent && ownerType == OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE + && UserRestrictionsUtils.isGlobal( + OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE, key))) { + setGlobalUserRestrictionInternal(admin, key, enabled); + } else { + int affectedUserId = parent + ? getProfileParentId(userId) : userId; + setLocalUserRestrictionInternal(admin, key, enabled, affectedUserId); + } + } else { + throw new IllegalStateException("Non-DO/Non-PO cannot set restriction " + key + + " while targetSdkVersion is less than UPSIDE_DOWN_CAKE"); } } @@ -24247,11 +24269,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Preconditions.checkCallAuthorization( hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)); return mInjector.binderWithCleanCallingIdentity(() -> { - boolean canForceMigration = forceMigration && !hasNonTestOnlyActiveAdmins(); - if (!canForceMigration && !shouldMigrateToDevicePolicyEngine()) { - return false; + synchronized (getLockObject()) { + boolean canForceMigration = forceMigration && !hasNonTestOnlyActiveAdmins(); + if (!canForceMigration && !shouldMigrateToDevicePolicyEngine()) { + return false; + } + boolean migrated = migratePoliciesToDevicePolicyEngine(); + migrated &= migratePoliciesPostUpgradeToDevicePolicyEngineLocked(); + return migrated; } - return migratePoliciesToDevicePolicyEngine(); }); } @@ -24281,6 +24307,31 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } /** + * [b/318497672] Migrate policies that weren't migrated properly in the initial migration on + * update from Android T to Android U + */ + private void maybeMigratePoliciesPostUpgradeToDevicePolicyEngineLocked() { + if (!mOwners.isMigratedToPolicyEngine() || mOwners.isMigratedPostUpdate()) { + return; + } + migratePoliciesPostUpgradeToDevicePolicyEngineLocked(); + mOwners.markPostUpgradeMigration(); + } + + private boolean migratePoliciesPostUpgradeToDevicePolicyEngineLocked() { + try { + migrateScreenCapturePolicyLocked(); + migrateLockTaskPolicyLocked(); + migrateUserRestrictionsLocked(); + return true; + } catch (Exception e) { + Slogf.e(LOG_TAG, e, "Error occurred during post upgrade migration to the device " + + "policy engine."); + return false; + } + } + + /** * @return {@code true} if policies were migrated successfully, {@code false} otherwise. */ private boolean migratePoliciesToDevicePolicyEngine() { @@ -24293,7 +24344,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { migrateAutoTimezonePolicy(); migratePermissionGrantStatePolicies(); } - migrateScreenCapturePolicyLocked(); migratePermittedInputMethodsPolicyLocked(); migrateAccountManagementDisabledPolicyLocked(); migrateUserControlDisabledPackagesLocked(); @@ -24366,14 +24416,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private void migrateScreenCapturePolicyLocked() { Binder.withCleanCallingIdentity(() -> { - if (mPolicyCache.getScreenCaptureDisallowedUser() == UserHandle.USER_NULL) { - return; - } ActiveAdmin admin = getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceLocked(); if (admin != null && ((isDeviceOwner(admin) && admin.disableScreenCapture) || (admin.getParentActiveAdmin() != null && admin.getParentActiveAdmin().disableScreenCapture))) { + EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin( admin.info.getComponent(), admin.getUserHandle().getIdentifier(), @@ -24402,6 +24450,48 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { }); } + private void migrateLockTaskPolicyLocked() { + Binder.withCleanCallingIdentity(() -> { + ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); + if (deviceOwner != null) { + int doUserId = deviceOwner.getUserHandle().getIdentifier(); + DevicePolicyData policies = getUserData(doUserId); + List<String> packages = policies.mLockTaskPackages; + int features = policies.mLockTaskFeatures; + // TODO: find out about persistent preferred activities + if (!packages.isEmpty()) { + setLockTaskPolicyInPolicyEngine(deviceOwner, doUserId, packages, features); + } + } + + for (int userId : mUserManagerInternal.getUserIds()) { + ActiveAdmin profileOwner = getProfileOwnerLocked(userId); + if (profileOwner != null && canDPCManagedUserUseLockTaskLocked(userId)) { + DevicePolicyData policies = getUserData(userId); + List<String> packages = policies.mLockTaskPackages; + int features = policies.mLockTaskFeatures; + if (!packages.isEmpty()) { + setLockTaskPolicyInPolicyEngine(profileOwner, userId, packages, features); + } + } + } + }); + } + + private void setLockTaskPolicyInPolicyEngine( + ActiveAdmin admin, int userId, List<String> packages, int features) { + EnforcingAdmin enforcingAdmin = + EnforcingAdmin.createEnterpriseEnforcingAdmin( + admin.info.getComponent(), + userId, + admin); + mDevicePolicyEngine.setLocalPolicy( + PolicyDefinition.LOCK_TASK, + enforcingAdmin, + new LockTaskPolicy(new HashSet<>(packages), features), + userId); + } + private void migratePermittedInputMethodsPolicyLocked() { Binder.withCleanCallingIdentity(() -> { List<UserInfo> users = mUserManager.getUsers(); @@ -24494,6 +24584,42 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { }); } + private void migrateUserRestrictionsLocked() { + Binder.withCleanCallingIdentity(() -> { + List<UserInfo> users = mUserManager.getUsers(); + for (UserInfo userInfo : users) { + ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(userInfo.id); + if (admin == null) continue; + ComponentName adminComponent = admin.info.getComponent(); + int userId = userInfo.id; + EnforcingAdmin enforcingAdmin = EnforcingAdmin.createEnterpriseEnforcingAdmin( + adminComponent, + userId, + admin); + int ownerType; + if (isDeviceOwner(admin)) { + ownerType = OWNER_TYPE_DEVICE_OWNER; + } else if (isProfileOwnerOfOrganizationOwnedDevice(adminComponent, userId)) { + ownerType = OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE; + } else if (isProfileOwner(adminComponent, userId)) { + ownerType = OWNER_TYPE_PROFILE_OWNER; + } else { + throw new IllegalStateException("Invalid DO/PO state"); + } + + for (final String restriction : admin.ensureUserRestrictions().keySet()) { + setBackwardCompatibleUserRestrictionLocked(ownerType, enforcingAdmin, userId, + restriction, /* enabled */ true, /* parent */ false); + } + for (final String restriction : admin.getParentActiveAdmin() + .ensureUserRestrictions().keySet()) { + setBackwardCompatibleUserRestrictionLocked(ownerType, enforcingAdmin, userId, + restriction, /* enabled */ true, /* parent */ true); + } + } + }); + } + private List<PackageInfo> getInstalledPackagesOnUser(int userId) { return mInjector.binderWithCleanCallingIdentity(() -> mContext.getPackageManager().getInstalledPackagesAsUser( diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java index bb275e45b55a..c842e29e3c70 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java @@ -616,6 +616,19 @@ class Owners { } } + void markPostUpgradeMigration() { + synchronized (mData) { + mData.mPoliciesMigratedPostUpdate = true; + mData.writeDeviceOwner(); + } + } + + boolean isMigratedPostUpdate() { + synchronized (mData) { + return mData.mPoliciesMigratedPostUpdate; + } + } + @GuardedBy("mData") void pushToAppOpsLocked() { if (!mSystemReady) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java b/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java index 37d4f95cac29..608ae140450e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java @@ -87,6 +87,8 @@ class OwnersData { private static final String ATTR_MIGRATED_TO_POLICY_ENGINE = "migratedToPolicyEngine"; + private static final String ATTR_MIGRATED_POST_UPGRADE = "migratedPostUpgrade"; + // Internal state for the device owner package. OwnerInfo mDeviceOwner; int mDeviceOwnerUserId = UserHandle.USER_NULL; @@ -114,6 +116,8 @@ class OwnersData { boolean mMigratedToPolicyEngine = false; + boolean mPoliciesMigratedPostUpdate = false; + OwnersData(PolicyPathProvider pathProvider) { mPathProvider = pathProvider; } @@ -397,6 +401,7 @@ class OwnersData { out.startTag(null, TAG_POLICY_ENGINE_MIGRATION); out.attributeBoolean(null, ATTR_MIGRATED_TO_POLICY_ENGINE, mMigratedToPolicyEngine); + out.attributeBoolean(null, ATTR_MIGRATED_POST_UPGRADE, mPoliciesMigratedPostUpdate); out.endTag(null, TAG_POLICY_ENGINE_MIGRATION); } @@ -457,6 +462,8 @@ class OwnersData { case TAG_POLICY_ENGINE_MIGRATION: mMigratedToPolicyEngine = parser.getAttributeBoolean( null, ATTR_MIGRATED_TO_POLICY_ENGINE, false); + mPoliciesMigratedPostUpdate = parser.getAttributeBoolean( + null, ATTR_MIGRATED_POST_UPGRADE, false); break; default: Slog.e(TAG, "Unexpected tag: " + tag); diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java index b539a76b521c..5eda84ba7629 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java @@ -146,6 +146,7 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { @SmallTest @Test + @Ignore("b/277916462") public void testCompMigrationUnAffiliated_skipped() throws Exception { prepareAdmin1AsDo(); prepareAdminAnotherPackageAsPo(COPE_PROFILE_USER_ID); @@ -217,6 +218,7 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { @SmallTest @Test + @Ignore("b/277916462") public void testCompMigration_keepSuspendedAppsWhenDpcIsRPlus() throws Exception { prepareAdmin1AsDo(); prepareAdmin1AsPo(COPE_PROFILE_USER_ID, Build.VERSION_CODES.R); @@ -250,6 +252,7 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase { @SmallTest @Test + @Ignore("b/277916462") public void testCompMigration_unsuspendAppsWhenDpcNotRPlus() throws Exception { prepareAdmin1AsDo(); prepareAdmin1AsPo(COPE_PROFILE_USER_ID, Build.VERSION_CODES.Q); 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 0ddd3135506e..7fb5c9687796 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -229,6 +229,26 @@ public class WindowStateTests extends WindowTestsBase { assertTrue(window.isOnScreen()); window.hide(false /* doAnimation */, false /* requestAnim */); assertFalse(window.isOnScreen()); + + // Verifies that a window without animation can be hidden even if its parent is animating. + window.show(false /* doAnimation */, false /* requestAnim */); + assertTrue(window.isVisibleByPolicy()); + window.getParent().startAnimation(mTransaction, mock(AnimationAdapter.class), + false /* hidden */, SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION); + window.mAttrs.windowAnimations = 0; + window.hide(true /* doAnimation */, true /* requestAnim */); + assertFalse(window.isSelfAnimating(0, SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION)); + assertFalse(window.isVisibleByPolicy()); + assertFalse(window.isOnScreen()); + + // Verifies that a window with animation can be hidden after the hide animation is finished. + window.show(false /* doAnimation */, false /* requestAnim */); + window.mAttrs.windowAnimations = android.R.style.Animation_Dialog; + window.hide(true /* doAnimation */, true /* requestAnim */); + assertTrue(window.isSelfAnimating(0, SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION)); + assertTrue(window.isVisibleByPolicy()); + window.cancelAnimation(); + assertFalse(window.isVisibleByPolicy()); } @Test diff --git a/tests/Input/AndroidTest.xml b/tests/Input/AndroidTest.xml index c62db1ea5ca9..13b5f0d99ba8 100644 --- a/tests/Input/AndroidTest.xml +++ b/tests/Input/AndroidTest.xml @@ -4,6 +4,7 @@ --> <configuration description="Runs Input Tests"> <option name="test-tag" value="InputTests" /> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" /> <target_preparer class="com.android.tradefed.targetprep.DeviceSetup"> <!-- keeps the screen on during tests --> <option name="screen-always-on" value="on" /> |