Merge "Resolve message/conversation image Uris with the correct user id" into tm-qpr-dev
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index 3f2fa21..16b18c85 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -31,6 +31,7 @@
import android.os.Process;
import android.permission.PermissionManager;
import android.util.ArraySet;
+import android.util.Log;
import com.android.internal.annotations.Immutable;
@@ -87,6 +88,8 @@
*/
@Immutable
public final class AttributionSource implements Parcelable {
+ private static final String TAG = "AttributionSource";
+
private static final String DESCRIPTOR = "android.content.AttributionSource";
private static final Binder sDefaultToken = new Binder(DESCRIPTOR);
@@ -154,9 +157,20 @@
AttributionSource(@NonNull Parcel in) {
this(AttributionSourceState.CREATOR.createFromParcel(in));
- // Since we just unpacked this object as part of it transiting a Binder
- // call, this is the perfect time to enforce that its UID and PID can be trusted
- enforceCallingUidAndPid();
+ if (!Binder.isDirectlyHandlingTransaction()) {
+ Log.e(TAG, "Unable to verify calling UID #" + mAttributionSourceState.uid + " PID #"
+ + mAttributionSourceState.pid + " when not handling Binder transaction; "
+ + "clearing.");
+ mAttributionSourceState.pid = -1;
+ mAttributionSourceState.uid = -1;
+ mAttributionSourceState.packageName = null;
+ mAttributionSourceState.attributionTag = null;
+ mAttributionSourceState.next = null;
+ } else {
+ // Since we just unpacked this object as part of it transiting a Binder
+ // call, this is the perfect time to enforce that its UID and PID can be trusted
+ enforceCallingUidAndPid();
+ }
}
/** @hide */
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index f224f8a1..2ec2b3b 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2740,6 +2740,16 @@
/**
* 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/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/KeyguardMediaController.kt
index 30ee147..2a2882c 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 @@
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.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 @@
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 @@
}
)
- 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
@@ -133,16 +104,6 @@
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
*/
@@ -202,7 +163,6 @@
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 54237ce..f0ff129 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 @@
) {
/** 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)
@@ -462,6 +462,7 @@
}
mediaCarouselController.mediaCarouselScrollHandler.visibleToUser =
isVisibleToUser()
+ mediaCarouselController.updateHostVisibility()
}
override fun onDozeAmountChanged(linear: Float, eased: Float) {
@@ -538,7 +539,6 @@
mediaCarouselController.updateHostVisibility = {
mediaHosts.forEach { it?.updateViewVisibility() }
}
-
panelEventsEvents.addShadeStateEventsListener(
object : ShadeStateEventsListener {
override fun onExpandImmediateChanged(isExpandImmediateEnabled: Boolean) {
@@ -552,12 +552,8 @@
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()
}
}
}
@@ -568,6 +564,14 @@
)
}
+ private fun getMediaLockScreenSetting(): Boolean {
+ return secureSettings.getBoolForUser(
+ Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN,
+ true,
+ UserHandle.USER_CURRENT
+ )
+ }
+
private fun updateConfiguration() {
distanceForFullShadeTransition =
context.resources.getDimensionPixelSize(
@@ -607,6 +611,13 @@
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 be570b4..26580e5 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 @@
*/
fun updateViewVisibility() {
state.visible =
- if (showsOnlyActiveMedia) {
+ if (mediaHierarchyManager.isLockedAndHidden()) {
+ false
+ } else if (showsOnlyActiveMedia) {
mediaDataManager.hasActiveMediaOrRecommendation()
} else {
mediaDataManager.hasAnyMediaOrRecommendation()
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 b40ebc9..41b3fe6 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.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 @@
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 @@
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 @@
}
@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 eb78ded..c2a7210 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 @@
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)
@@ -470,6 +471,55 @@
)
}
+ @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/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 1c3564b..bc13f10 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3561,6 +3561,11 @@
// 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,
@@ -5146,6 +5151,11 @@
} 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/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 8dadd31..96c34db 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -678,6 +678,7 @@
// TODO: switch this back to SecurityException
Slog.wtf(TAG, "Not allowed to modify non-dynamic permission "
+ permName);
+ return;
}
mRegistry.removePermission(permName);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b9d43d9..bc8e235 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3296,8 +3296,10 @@
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/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 219f441..44ae8dd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -227,6 +227,26 @@
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/BootImageProfileTest/AndroidTest.xml b/tests/BootImageProfileTest/AndroidTest.xml
index 7e97fa3..50f323c 100644
--- a/tests/BootImageProfileTest/AndroidTest.xml
+++ b/tests/BootImageProfileTest/AndroidTest.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
<configuration description="Config for BootImageProfileTest">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
<!-- do not use DeviceSetup#set-property because it reboots the device b/136200738.
furthermore the changes in /data/local.prop don't actually seem to get picked up.
-->