diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-01-24 18:08:31 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-01-24 18:08:31 +0000 |
commit | b4e3fdfeea81b20fb5ef7ddcda4615cba0a9db13 (patch) | |
tree | 8ecdae832d752b35d251819098b7153076b66903 | |
parent | fbdca2eaca667dd17682d3fb306a5971dff4dc0a (diff) | |
parent | cbedf08fcd8cc379a23d6caecef74598480500b8 (diff) | |
download | base-b4e3fdfeea81b20fb5ef7ddcda4615cba0a9db13.tar.gz |
Merge cherrypicks of ['ag/20272083', 'ag/20346940', 'ag/20082616', 'ag/20482625'] into sc-platform-release.android-platform-12.0.0_r17
Change-Id: I6eaca2b132fa037deeac34546ea3dea4cf31cdfd
8 files changed, 142 insertions, 36 deletions
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java index 6588b5748d09..cc7cf241e3c9 100644 --- a/core/java/android/os/WorkSource.java +++ b/core/java/android/os/WorkSource.java @@ -128,7 +128,7 @@ public class WorkSource implements Parcelable { mNames = in.createStringArray(); int numChains = in.readInt(); - if (numChains > 0) { + if (numChains >= 0) { mChains = new ArrayList<>(numChains); in.readParcelableList(mChains, WorkChain.class.getClassLoader()); } else { diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl index 9bf126b7a875..31fb8d03c4a0 100644 --- a/media/java/android/media/session/ISession.aidl +++ b/media/java/android/media/session/ISession.aidl @@ -35,7 +35,7 @@ interface ISession { ISessionController getController(); void setFlags(int flags); void setActive(boolean active); - void setMediaButtonReceiver(in PendingIntent mbr, String sessionPackageName); + void setMediaButtonReceiver(in PendingIntent mbr); void setMediaButtonBroadcastReceiver(in ComponentName broadcastReceiver); void setLaunchPendingIntent(in PendingIntent pi); void destroySession(); diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index 20fa53d3ec32..24118b086c24 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -286,7 +286,7 @@ public final class MediaSession { @Deprecated public void setMediaButtonReceiver(@Nullable PendingIntent mbr) { try { - mBinder.setMediaButtonReceiver(mbr, mContext.getPackageName()); + mBinder.setMediaButtonReceiver(mbr); } catch (RemoteException e) { Log.wtf(TAG, "Failure in setMediaButtonReceiver.", e); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java index 18d6e646b007..dc9f2ce69f9d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java @@ -41,6 +41,7 @@ import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusIconContainer; import com.android.systemui.statusbar.policy.Clock; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.VariableDateViewController; import com.android.systemui.util.ViewController; @@ -71,6 +72,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader private final PrivacyDialogController mPrivacyDialogController; private final QSExpansionPathInterpolator mQSExpansionPathInterpolator; private final FeatureFlags mFeatureFlags; + private final DeviceProvisionedController mDeviceProvisionedController; private final VariableDateViewController mVariableDateViewControllerDateView; private final VariableDateViewController mVariableDateViewControllerClockDateView; @@ -79,6 +81,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader private boolean mMicCameraIndicatorsEnabled; private boolean mLocationIndicatorsEnabled; private boolean mPrivacyChipLogged; + private volatile boolean mDeviceProvisioned; private final String mCameraSlot; private final String mMicSlot; private final String mLocationSlot; @@ -119,6 +122,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader @Override public void onClick(View v) { if (v == mPrivacyChip) { + if (!mDeviceProvisioned) return; // If the privacy chip is visible, it means there were some indicators mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_CLICK); mPrivacyDialogController.showDialog(getContext()); @@ -126,6 +130,14 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader } }; + private DeviceProvisionedController.DeviceProvisionedListener mDeviceProvisionedListener = + new DeviceProvisionedController.DeviceProvisionedListener() { + @Override + public void onDeviceProvisionedChanged() { + mDeviceProvisioned = mDeviceProvisionedController.isDeviceProvisioned(); + } + }; + @Inject QuickStatusBarHeaderController(QuickStatusBarHeader view, PrivacyItemController privacyItemController, @@ -139,7 +151,8 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader PrivacyDialogController privacyDialogController, QSExpansionPathInterpolator qsExpansionPathInterpolator, FeatureFlags featureFlags, - VariableDateViewController.Factory variableDateViewControllerFactory) { + VariableDateViewController.Factory variableDateViewControllerFactory, + DeviceProvisionedController deviceProvisionedController) { super(view); mPrivacyItemController = privacyItemController; mActivityStarter = activityStarter; @@ -151,6 +164,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader mPrivacyDialogController = privacyDialogController; mQSExpansionPathInterpolator = qsExpansionPathInterpolator; mFeatureFlags = featureFlags; + mDeviceProvisionedController = deviceProvisionedController; mQSCarrierGroupController = qsCarrierGroupControllerBuilder .setQSCarrierGroup(mView.findViewById(R.id.carrier_group)) @@ -182,6 +196,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader @Override protected void onViewAttached() { + mDeviceProvisionedController.addCallback(mDeviceProvisionedListener); mPrivacyChip.setOnClickListener(mOnClickListener); mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable(); @@ -224,6 +239,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader @Override protected void onViewDetached() { mColorExtractor.removeOnColorsChangedListener(mOnColorsChangedListener); + mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener); mPrivacyChip.setOnClickListener(null); mStatusBarIconController.removeIconGroup(mIconManager); mQSCarrierGroupController.setOnSingleCarrierChangedListener(null); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt index 8b7e20ed0e5a..552f60d252bc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt @@ -36,6 +36,7 @@ import com.android.systemui.statusbar.FeatureFlags import com.android.systemui.statusbar.phone.StatusBarIconController import com.android.systemui.statusbar.phone.StatusIconContainer import com.android.systemui.statusbar.policy.Clock +import com.android.systemui.statusbar.policy.DeviceProvisionedController import com.android.systemui.statusbar.policy.VariableDateView import com.android.systemui.statusbar.policy.VariableDateViewController import com.android.systemui.util.mockito.any @@ -50,6 +51,7 @@ import org.mockito.Answers import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.Mockito.`when` +import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -103,6 +105,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { @Mock private lateinit var featureFlags: FeatureFlags + private lateinit var deviceProvisionedController: FakeDeviceProvisionedController private val qsExpansionPathInterpolator = QSExpansionPathInterpolator() private lateinit var controller: QuickStatusBarHeaderController @@ -123,6 +126,9 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { `when`(view.isAttachedToWindow).thenReturn(true) `when`(view.context).thenReturn(context) + deviceProvisionedController = FakeDeviceProvisionedController() + deviceProvisionedController.provisioned = true + cameraSlotName = mContext.resources.getString( com.android.internal.R.string.status_bar_camera) microphoneSlotName = mContext.resources.getString( @@ -144,7 +150,8 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { privacyDialogController, qsExpansionPathInterpolator, featureFlags, - variableDateViewControllerFactory + variableDateViewControllerFactory, + deviceProvisionedController ) } @@ -279,6 +286,34 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { verify(view).setIsSingleCarrier(false) } + @Test + fun testDeviceNotProvisionedBeforeInit_clickOnChipDoesntShowDialog() { + deviceProvisionedController.provisioned = false + controller.init() + + val captor = argumentCaptor<View.OnClickListener>() + verify(privacyChip).setOnClickListener(capture(captor)) + + captor.value.onClick(privacyChip) + + verify(privacyDialogController, never()).showDialog(any(Context::class.java)) + } + + @Test + fun testDeviceNotProvisionedBeforeInit_provisionedAfter_clickOnChipDoesntShowDialog() { + deviceProvisionedController.provisioned = false + controller.init() + + deviceProvisionedController.provisioned = true + + val captor = argumentCaptor<View.OnClickListener>() + verify(privacyChip).setOnClickListener(capture(captor)) + + captor.value.onClick(privacyChip) + + verify(privacyDialogController).showDialog(any(Context::class.java)) + } + private fun stubViews() { `when`(view.findViewById<View>(anyInt())).thenReturn(mockView) `when`(view.findViewById<QSCarrierGroup>(R.id.carrier_group)).thenReturn(qsCarrierGroup) @@ -293,4 +328,40 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { `when`(privacyItemController.micCameraAvailable).thenReturn(micCamera) `when`(privacyItemController.locationAvailable).thenReturn(location) } + + // We only care about device provisioned + class FakeDeviceProvisionedController : DeviceProvisionedController { + val callbacks = mutableSetOf<DeviceProvisionedController.DeviceProvisionedListener>() + var provisioned = false + set(value) { + if (field != value) { + field = value + callbacks.forEach { it.onDeviceProvisionedChanged() } + } + } + + override fun addCallback(listener: DeviceProvisionedController.DeviceProvisionedListener) { + if (callbacks.add(listener)) { + listener.onDeviceProvisionedChanged() + } + } + + override fun removeCallback( + listener: DeviceProvisionedController.DeviceProvisionedListener + ) { + callbacks.remove(listener) + } + + override fun isDeviceProvisioned(): Boolean { + return provisioned + } + + override fun isUserSetup(currentUser: Int): Boolean { + return true + } + + override fun getCurrentUser(): Int { + return 0 + } + } } diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java index 9a190316f4eb..c5fb5270f841 100644 --- a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java +++ b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java @@ -18,6 +18,7 @@ package com.android.server.media; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.BroadcastOptions; import android.app.PendingIntent; import android.content.ComponentName; @@ -37,6 +38,7 @@ import android.view.KeyEvent; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Collections; import java.util.List; /** @@ -102,15 +104,19 @@ final class MediaButtonReceiverHolder { } /** - * Creates a new instance. + * Creates a new instance from a {@link PendingIntent}. + * + * <p>This method assumes the session package name has been validated and effectively belongs to + * the media session's owner. * - * @param context context * @param userId userId - * @param pendingIntent pending intent - * @return Can be {@code null} if pending intent was null. + * @param pendingIntent pending intent that will receive media button events + * @param sessionPackageName package name of media session owner + * @return {@link MediaButtonReceiverHolder} instance or {@code null} if pending intent was + * null. */ - public static MediaButtonReceiverHolder create(Context context, int userId, - PendingIntent pendingIntent, String sessionPackageName) { + public static MediaButtonReceiverHolder create( + int userId, @Nullable PendingIntent pendingIntent, String sessionPackageName) { if (pendingIntent == null) { return null; } @@ -312,7 +318,7 @@ final class MediaButtonReceiverHolder { } private static ComponentName getComponentName(PendingIntent pendingIntent, int componentType) { - List<ResolveInfo> resolveInfos = null; + List<ResolveInfo> resolveInfos = Collections.emptyList(); switch (componentType) { case COMPONENT_TYPE_ACTIVITY: resolveInfos = pendingIntent.queryIntentComponents( @@ -330,32 +336,37 @@ final class MediaButtonReceiverHolder { PACKAGE_MANAGER_COMMON_FLAGS | PackageManager.GET_RECEIVERS); break; } - if (resolveInfos != null && !resolveInfos.isEmpty()) { - return createComponentName(resolveInfos.get(0)); + + for (ResolveInfo resolveInfo : resolveInfos) { + ComponentInfo componentInfo = getComponentInfo(resolveInfo); + if (componentInfo != null && TextUtils.equals(componentInfo.packageName, + pendingIntent.getCreatorPackage()) + && componentInfo.packageName != null && componentInfo.name != null) { + return new ComponentName(componentInfo.packageName, componentInfo.name); + } } + return null; } - private static ComponentName createComponentName(ResolveInfo resolveInfo) { - if (resolveInfo == null) { - return null; - } - ComponentInfo componentInfo; + /** + * Retrieves the {@link ComponentInfo} from a {@link ResolveInfo} instance. Similar to {@link + * ResolveInfo#getComponentInfo()}, but returns {@code null} if this {@link ResolveInfo} points + * to a content provider. + * + * @param resolveInfo Where to extract the {@link ComponentInfo} from. + * @return Either a non-null {@link ResolveInfo#activityInfo} or {@link + * ResolveInfo#serviceInfo}. Otherwise {@code null} if {@link ResolveInfo#providerInfo} is + * not {@code null}. + */ + private static ComponentInfo getComponentInfo(@NonNull ResolveInfo resolveInfo) { // Code borrowed from ResolveInfo#getComponentInfo(). if (resolveInfo.activityInfo != null) { - componentInfo = resolveInfo.activityInfo; + return resolveInfo.activityInfo; } else if (resolveInfo.serviceInfo != null) { - componentInfo = resolveInfo.serviceInfo; + return resolveInfo.serviceInfo; } else { - // We're not interested in content provider. - return null; - } - // Code borrowed from ComponentInfo#getComponentName(). - try { - return new ComponentName(componentInfo.packageName, componentInfo.name); - } catch (IllegalArgumentException | NullPointerException e) { - // This may be happen if resolveActivity() end up with matching multiple activities. - // see PackageManager#resolveActivity(). + // We're not interested in content providers. return null; } } diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 4822d6a62ac7..9bbcec98ef71 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -53,6 +53,7 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.SystemClock; import android.text.TextUtils; +import android.util.EventLog; import android.util.Log; import android.view.KeyEvent; @@ -932,8 +933,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR } @Override - public void setMediaButtonReceiver(PendingIntent pi, String sessionPackageName) - throws RemoteException { + public void setMediaButtonReceiver(PendingIntent pi) throws RemoteException { final long token = Binder.clearCallingIdentity(); try { if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER) @@ -941,7 +941,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR return; } mMediaButtonReceiverHolder = - MediaButtonReceiverHolder.create(mContext, mUserId, pi, sessionPackageName); + MediaButtonReceiverHolder.create(mUserId, pi, mPackageName); mService.onMediaButtonReceiverChanged(MediaSessionRecord.this); } finally { Binder.restoreCallingIdentity(token); @@ -952,6 +952,14 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR public void setMediaButtonBroadcastReceiver(ComponentName receiver) throws RemoteException { final long token = Binder.clearCallingIdentity(); try { + //mPackageName has been verified in MediaSessionService.enforcePackageName(). + if (receiver != null && !TextUtils.equals( + mPackageName, receiver.getPackageName())) { + EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet logging. + throw new IllegalArgumentException("receiver does not belong to " + + "package name provided to MediaSessionRecord. Pkg = " + mPackageName + + ", Receiver Pkg = " + receiver.getPackageName()); + } if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER) != 0) { return; diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index b477ea353c25..52f97574a03b 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -2229,9 +2229,9 @@ public class MediaSessionService extends SystemService implements Monitor { PendingIntent pi = mCustomMediaKeyDispatcher.getMediaButtonReceiver(keyEvent, uid, asSystemService); if (pi != null) { - mediaButtonReceiverHolder = MediaButtonReceiverHolder.create(mContext, - mCurrentFullUserRecord.mFullUserId, pi, - /* sessionPackageName= */ ""); + mediaButtonReceiverHolder = + MediaButtonReceiverHolder.create( + mCurrentFullUserRecord.mFullUserId, pi, ""); } } } |