[coastguard skipped] Merge sparse cherrypicks from sparse-9583930-L95100000958584662 into tm-d4-release. COASTGUARD_SKIP: I5620b0c507322026f3e64aac0c411b6b1373610a COASTGUARD_SKIP: I56c2fc14f906cdad80181ab577e2ebc276c151c1 Change-Id: I80ea76405e3ce87f9d22603bd61a6a203e468179
diff --git a/core/java/android/hardware/fingerprint/IUdfpsHbmListener.aidl b/core/java/android/hardware/fingerprint/IUdfpsHbmListener.aidl index 9c2aa66..a36ccf6 100644 --- a/core/java/android/hardware/fingerprint/IUdfpsHbmListener.aidl +++ b/core/java/android/hardware/fingerprint/IUdfpsHbmListener.aidl
@@ -39,5 +39,15 @@ * {@link android.view.Display#getDisplayId()}. */ void onHbmDisabled(int displayId); + + /** + * To avoid delay in switching refresh rate when activating LHBM, allow screens to request + * higher refersh rate if auth is possible on particular screen + * + * @param displayId The displayId for which the refresh rate should be unset. See + * {@link android.view.Display#getDisplayId()}. + * @param isPossible If authentication is possible on particualr screen + */ + void onAuthenticationPossible(int displayId, boolean isPossible); }
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java index e899f77..65528e3 100644 --- a/core/java/android/os/WorkSource.java +++ b/core/java/android/os/WorkSource.java
@@ -128,7 +128,7 @@ mNames = in.createStringArray(); int numChains = in.readInt(); - if (numChains > 0) { + if (numChains >= 0) { mChains = new ArrayList<>(numChains); in.readParcelableList(mChains, WorkChain.class.getClassLoader(), android.os.WorkSource.WorkChain.class); } else {
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl index 9bf126b..31fb8d0 100644 --- a/media/java/android/media/session/ISession.aidl +++ b/media/java/android/media/session/ISession.aidl
@@ -35,7 +35,7 @@ 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 bc00c40..84ecc06 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java
@@ -286,7 +286,7 @@ @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/res-keyguard/layout/keyguard_bouncer_user_switcher.xml b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher.xml index 898935f..2cac9c7 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_user_switcher.xml
@@ -21,8 +21,6 @@ android:id="@+id/keyguard_bouncer_user_switcher" android:layout_width="match_parent" android:layout_height="wrap_content" - android:clipChildren="false" - android:clipToPadding="false" android:orientation="vertical" android:gravity="center" android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 5c4126e..8f3484a 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -221,10 +221,11 @@ public void onEnd(WindowInsetsAnimation animation) { if (!mDisappearAnimRunning) { endJankInstrument(InteractionJankMonitor.CUJ_LOCKSCREEN_PASSWORD_APPEAR); - updateChildren(0 /* translationY */, 1f /* alpha */); } else { endJankInstrument(InteractionJankMonitor.CUJ_LOCKSCREEN_PASSWORD_DISAPPEAR); + setAlpha(0f); } + updateChildren(0 /* translationY */, 1f /* alpha */); } private void updateChildren(int translationY, float alpha) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 90ed293..9a898f9 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -93,6 +93,7 @@ import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricSourceType; import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; +import android.hardware.biometrics.SensorProperties; import android.hardware.face.FaceManager; import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.fingerprint.FingerprintManager; @@ -2952,6 +2953,23 @@ return isUnlockWithFacePossible(userId) || isUnlockWithFingerprintPossible(userId); } + /** + * If non-strong (i.e. weak or convenience) biometrics hardware is available, not disabled, and + * user has enrolled templates. This does NOT check if the device is encrypted or in lockdown. + * + * @param userId User that's trying to unlock. + * @return {@code true} if possible. + */ + public boolean isUnlockingWithNonStrongBiometricsPossible(int userId) { + // This assumes that there is at most one face and at most one fingerprint sensor + return (mFaceManager != null && !mFaceSensorProperties.isEmpty() + && (mFaceSensorProperties.get(0).sensorStrength != SensorProperties.STRENGTH_STRONG) + && isUnlockWithFacePossible(userId)) + || (mFpm != null && !mFingerprintSensorProperties.isEmpty() + && (mFingerprintSensorProperties.get(0).sensorStrength + != SensorProperties.STRENGTH_STRONG) && isUnlockWithFingerprintPossible(userId)); + } + @SuppressLint("MissingPermission") @VisibleForTesting boolean isUnlockWithFingerprintPossible(int userId) {
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java index 82e5704..805a20a 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
@@ -16,15 +16,21 @@ package com.android.systemui.clipboardoverlay; +import static android.content.ClipDescription.CLASSIFICATION_COMPLETE; + import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_ENABLED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED; +import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_TOAST_SHOWN; + +import static com.google.android.setupcompat.util.WizardManagerHelper.SETTINGS_SECURE_USER_SETUP_COMPLETE; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.os.SystemProperties; import android.provider.DeviceConfig; +import android.provider.Settings; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -56,6 +62,7 @@ private final DeviceConfigProxy mDeviceConfig; private final Provider<ClipboardOverlayController> mOverlayProvider; private final ClipboardOverlayControllerLegacyFactory mOverlayFactory; + private final ClipboardToast mClipboardToast; private final ClipboardManager mClipboardManager; private final UiEventLogger mUiEventLogger; private final FeatureFlags mFeatureFlags; @@ -66,6 +73,7 @@ public ClipboardListener(Context context, DeviceConfigProxy deviceConfigProxy, Provider<ClipboardOverlayController> clipboardOverlayControllerProvider, ClipboardOverlayControllerLegacyFactory overlayFactory, + ClipboardToast clipboardToast, ClipboardManager clipboardManager, UiEventLogger uiEventLogger, FeatureFlags featureFlags) { @@ -73,6 +81,7 @@ mDeviceConfig = deviceConfigProxy; mOverlayProvider = clipboardOverlayControllerProvider; mOverlayFactory = overlayFactory; + mClipboardToast = clipboardToast; mClipboardManager = clipboardManager; mUiEventLogger = uiEventLogger; mFeatureFlags = featureFlags; @@ -102,6 +111,15 @@ return; } + if (!isUserSetupComplete()) { + // just show a toast, user should not access intents from this state + if (shouldShowToast(clipData)) { + mUiEventLogger.log(CLIPBOARD_TOAST_SHOWN, 0, clipSource); + mClipboardToast.showCopiedToast(); + } + return; + } + boolean enabled = mFeatureFlags.isEnabled(Flags.CLIPBOARD_OVERLAY_REFACTOR); if (mClipboardOverlay == null || enabled != mUsingNewOverlay) { mUsingNewOverlay = enabled; @@ -136,10 +154,26 @@ return clipData.getDescription().getExtras().getBoolean(EXTRA_SUPPRESS_OVERLAY, false); } + boolean shouldShowToast(ClipData clipData) { + if (clipData == null) { + return false; + } else if (clipData.getDescription().getClassificationStatus() == CLASSIFICATION_COMPLETE) { + // only show for classification complete if we aren't already showing a toast, to ignore + // the duplicate ClipData with classification + return !mClipboardToast.isShowing(); + } + return true; + } + private static boolean isEmulator() { return SystemProperties.getBoolean("ro.boot.qemu", false); } + private boolean isUserSetupComplete() { + return Settings.Secure.getInt(mContext.getContentResolver(), + SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1; + } + interface ClipboardOverlay { void setClipData(ClipData clipData, String clipSource);
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java index a0b2ab9..1e7dbe6 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java
@@ -41,7 +41,9 @@ @UiEvent(doc = "clipboard overlay tapped outside") CLIPBOARD_OVERLAY_TAP_OUTSIDE(1077), @UiEvent(doc = "clipboard overlay dismissed, miscellaneous reason") - CLIPBOARD_OVERLAY_DISMISSED_OTHER(1078); + CLIPBOARD_OVERLAY_DISMISSED_OTHER(1078), + @UiEvent(doc = "clipboard toast shown") + CLIPBOARD_TOAST_SHOWN(1270); private final int mId;
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardToast.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardToast.java new file mode 100644 index 0000000..0ed7d27 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardToast.java
@@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.clipboardoverlay; + +import android.content.Context; +import android.widget.Toast; + +import com.android.systemui.R; + +import javax.inject.Inject; + +/** + * Utility class for showing a simple clipboard toast on copy. + */ +class ClipboardToast extends Toast.Callback { + private final Context mContext; + private Toast mCopiedToast; + + @Inject + ClipboardToast(Context context) { + mContext = context; + } + + void showCopiedToast() { + if (mCopiedToast != null) { + mCopiedToast.cancel(); + } + mCopiedToast = Toast.makeText(mContext, + R.string.clipboard_overlay_text_copied, Toast.LENGTH_SHORT); + mCopiedToast.show(); + } + + boolean isShowing() { + return mCopiedToast != null; + } + + @Override // Toast.Callback + public void onToastHidden() { + super.onToastHidden(); + mCopiedToast = null; + } +}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 6ed5550..739b325 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2411,15 +2411,28 @@ } mKeyguardDisplayManager.show(); - // schedule 4hr idle timeout after which non-strong biometrics (i.e. weak or convenience - // biometric) can't be used to unlock device until unlocking with strong biometric or - // primary auth (i.e. PIN/pattern/password) - mLockPatternUtils.scheduleNonStrongBiometricIdleTimeout( - KeyguardUpdateMonitor.getCurrentUser()); + scheduleNonStrongBiometricIdleTimeout(); Trace.endSection(); } + /** + * Schedule 4-hour idle timeout for non-strong biometrics when the device is locked + */ + private void scheduleNonStrongBiometricIdleTimeout() { + final int currentUser = KeyguardUpdateMonitor.getCurrentUser(); + // If unlocking with non-strong (i.e. weak or convenience) biometrics is possible, schedule + // 4hr idle timeout after which non-strong biometrics can't be used to unlock device until + // unlocking with strong biometric or primary auth (i.e. PIN/pattern/password) + if (mUpdateMonitor.isUnlockingWithNonStrongBiometricsPossible(currentUser)) { + if (DEBUG) { + Log.d(TAG, "scheduleNonStrongBiometricIdleTimeout: schedule an alarm for " + + "currentUser=" + currentUser); + } + mLockPatternUtils.scheduleNonStrongBiometricIdleTimeout(currentUser); + } + } + private final Runnable mKeyguardGoingAwayRunnable = new Runnable() { @Override public void run() { @@ -2898,6 +2911,8 @@ if (DEBUG) Log.d(TAG, "handleReset"); mKeyguardViewControllerLazy.get().reset(true /* hideBouncerWhenShowing */); } + + scheduleNonStrongBiometricIdleTimeout(); } /**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java index 7cf63f6..1da30ad 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
@@ -36,7 +36,6 @@ void removeCallback(Callback callback); void removeTile(String tileSpec); void removeTiles(Collection<String> specs); - void unmarkTileAsAutoAdded(String tileSpec); int indexOf(String tileSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java index 6240c10..2be3d15 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -427,11 +427,6 @@ mMainExecutor.execute(() -> changeTileSpecs(tileSpecs -> tileSpecs.removeAll(specs))); } - @Override - public void unmarkTileAsAutoAdded(String spec) { - if (mAutoTiles != null) mAutoTiles.unmarkTileAsAutoAdded(spec); - } - /** * Add a tile to the end *
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java index 7130294..d3f0566 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -98,7 +98,6 @@ @Override public void onManagedProfileRemoved() { mHost.removeTile(getTileSpec()); - mHost.unmarkTileAsAutoAdded(getTileSpec()); } @Override
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt index 28da38b..61390c5 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -112,7 +112,7 @@ // These get called when a managed profile goes in or out of quiet mode. addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE) addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE) - + addAction(Intent.ACTION_MANAGED_PROFILE_ADDED) addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED) addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED) } @@ -129,6 +129,7 @@ Intent.ACTION_USER_INFO_CHANGED, Intent.ACTION_MANAGED_PROFILE_AVAILABLE, Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE, + Intent.ACTION_MANAGED_PROFILE_ADDED, Intent.ACTION_MANAGED_PROFILE_REMOVED, Intent.ACTION_MANAGED_PROFILE_UNLOCKED -> { handleProfilesChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java index 9070ead..149ec54 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -154,9 +154,7 @@ if (!mAutoTracker.isAdded(SAVER)) { mDataSaverController.addCallback(mDataSaverListener); } - if (!mAutoTracker.isAdded(WORK)) { - mManagedProfileController.addCallback(mProfileCallback); - } + mManagedProfileController.addCallback(mProfileCallback); if (!mAutoTracker.isAdded(NIGHT) && ColorDisplayManager.isNightDisplayAvailable(mContext)) { mNightDisplayListener.setCallback(mNightDisplayCallback); @@ -275,18 +273,18 @@ return mCurrentUser.getIdentifier(); } - public void unmarkTileAsAutoAdded(String tabSpec) { - mAutoTracker.setTileRemoved(tabSpec); - } - private final ManagedProfileController.Callback mProfileCallback = new ManagedProfileController.Callback() { @Override public void onManagedProfileChanged() { - if (mAutoTracker.isAdded(WORK)) return; if (mManagedProfileController.hasActiveProfile()) { + if (mAutoTracker.isAdded(WORK)) return; mHost.addTile(WORK); mAutoTracker.setTileAdded(WORK); + } else { + if (!mAutoTracker.isAdded(WORK)) return; + mHost.removeTile(WORK); + mAutoTracker.setTileRemoved(WORK); } } @@ -429,7 +427,7 @@ initSafetyTile(); } else if (!isSafetyCenterEnabled && mAutoTracker.isAdded(mSafetySpec)) { mHost.removeTile(mSafetySpec); - mHost.unmarkTileAsAutoAdded(mSafetySpec); + mAutoTracker.setTileRemoved(mSafetySpec); } } };
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java index e7e6918..bdd496e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java
@@ -18,6 +18,8 @@ import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_ENABLED; +import static com.google.android.setupcompat.util.WizardManagerHelper.SETTINGS_SECURE_USER_SETUP_COMPLETE; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -32,6 +34,7 @@ import android.content.ClipboardManager; import android.os.PersistableBundle; import android.provider.DeviceConfig; +import android.provider.Settings; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -66,6 +69,8 @@ @Mock private ClipboardOverlayController mOverlayController; @Mock + private ClipboardToast mClipboardToast; + @Mock private UiEventLogger mUiEventLogger; @Mock private FeatureFlags mFeatureFlags; @@ -84,6 +89,8 @@ @Spy private Provider<ClipboardOverlayController> mOverlayControllerProvider; + private ClipboardListener mClipboardListener; + @Before public void setup() { @@ -93,7 +100,8 @@ when(mClipboardOverlayControllerLegacyFactory.create(any())) .thenReturn(mOverlayControllerLegacy); when(mClipboardManager.hasPrimaryClip()).thenReturn(true); - + Settings.Secure.putInt( + mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 1); mSampleClipData = new ClipData("Test", new String[]{"text/plain"}, new ClipData.Item("Test Item")); @@ -101,16 +109,17 @@ when(mClipboardManager.getPrimaryClipSource()).thenReturn(mSampleSource); mDeviceConfigProxy = new DeviceConfigProxyFake(); + + mClipboardListener = new ClipboardListener(getContext(), mDeviceConfigProxy, + mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory, + mClipboardToast, mClipboardManager, mUiEventLogger, mFeatureFlags); } @Test public void test_disabled() { mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED, "false", false); - ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy, - mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory, - mClipboardManager, mUiEventLogger, mFeatureFlags); - listener.start(); + mClipboardListener.start(); verifyZeroInteractions(mClipboardManager); verifyZeroInteractions(mUiEventLogger); } @@ -119,10 +128,7 @@ public void test_enabled() { mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED, "true", false); - ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy, - mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory, - mClipboardManager, mUiEventLogger, mFeatureFlags); - listener.start(); + mClipboardListener.start(); verify(mClipboardManager).addPrimaryClipChangedListener(any()); verifyZeroInteractions(mUiEventLogger); } @@ -133,11 +139,8 @@ mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED, "true", false); - ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy, - mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory, - mClipboardManager, mUiEventLogger, mFeatureFlags); - listener.start(); - listener.onPrimaryClipChanged(); + mClipboardListener.start(); + mClipboardListener.onPrimaryClipChanged(); verify(mClipboardOverlayControllerLegacyFactory).create(any()); @@ -152,14 +155,14 @@ // Should clear the overlay controller mRunnableCaptor.getValue().run(); - listener.onPrimaryClipChanged(); + mClipboardListener.onPrimaryClipChanged(); verify(mClipboardOverlayControllerLegacyFactory, times(2)).create(any()); // Not calling the runnable here, just change the clip again and verify that the overlay is // NOT recreated. - listener.onPrimaryClipChanged(); + mClipboardListener.onPrimaryClipChanged(); verify(mClipboardOverlayControllerLegacyFactory, times(2)).create(any()); verifyZeroInteractions(mOverlayControllerProvider); @@ -171,11 +174,8 @@ mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED, "true", false); - ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy, - mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory, - mClipboardManager, mUiEventLogger, mFeatureFlags); - listener.start(); - listener.onPrimaryClipChanged(); + mClipboardListener.start(); + mClipboardListener.onPrimaryClipChanged(); verify(mOverlayControllerProvider).get(); @@ -190,14 +190,14 @@ // Should clear the overlay controller mRunnableCaptor.getValue().run(); - listener.onPrimaryClipChanged(); + mClipboardListener.onPrimaryClipChanged(); verify(mOverlayControllerProvider, times(2)).get(); // Not calling the runnable here, just change the clip again and verify that the overlay is // NOT recreated. - listener.onPrimaryClipChanged(); + mClipboardListener.onPrimaryClipChanged(); verify(mOverlayControllerProvider, times(2)).get(); verifyZeroInteractions(mClipboardOverlayControllerLegacyFactory); @@ -233,13 +233,10 @@ public void test_logging_enterAndReenter() { when(mFeatureFlags.isEnabled(Flags.CLIPBOARD_OVERLAY_REFACTOR)).thenReturn(false); - ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy, - mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory, - mClipboardManager, mUiEventLogger, mFeatureFlags); - listener.start(); + mClipboardListener.start(); - listener.onPrimaryClipChanged(); - listener.onPrimaryClipChanged(); + mClipboardListener.onPrimaryClipChanged(); + mClipboardListener.onPrimaryClipChanged(); verify(mUiEventLogger, times(1)).log( ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED, 0, mSampleSource); @@ -251,17 +248,29 @@ public void test_logging_enterAndReenter_new() { when(mFeatureFlags.isEnabled(Flags.CLIPBOARD_OVERLAY_REFACTOR)).thenReturn(true); - ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy, - mOverlayControllerProvider, mClipboardOverlayControllerLegacyFactory, - mClipboardManager, mUiEventLogger, mFeatureFlags); - listener.start(); + mClipboardListener.start(); - listener.onPrimaryClipChanged(); - listener.onPrimaryClipChanged(); + mClipboardListener.onPrimaryClipChanged(); + mClipboardListener.onPrimaryClipChanged(); verify(mUiEventLogger, times(1)).log( ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED, 0, mSampleSource); verify(mUiEventLogger, times(1)).log( ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED, 0, mSampleSource); } + + @Test + public void test_userSetupIncomplete_showsToast() { + Settings.Secure.putInt( + mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0); + + mClipboardListener.start(); + mClipboardListener.onPrimaryClipChanged(); + + verify(mUiEventLogger, times(1)).log( + ClipboardOverlayEvent.CLIPBOARD_TOAST_SHOWN, 0, mSampleSource); + verify(mClipboardToast, times(1)).showCopiedToast(); + verifyZeroInteractions(mOverlayControllerProvider); + verifyZeroInteractions(mClipboardOverlayControllerLegacyFactory); + } }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt new file mode 100644 index 0000000..3710281 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
@@ -0,0 +1,100 @@ +package com.android.systemui.settings + +import android.content.Context +import android.content.Intent +import android.content.pm.UserInfo +import android.os.Handler +import android.os.UserHandle +import android.os.UserManager +import androidx.concurrent.futures.DirectExecutor +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.dump.DumpManager +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.capture +import com.google.common.truth.Truth.assertThat +import java.util.concurrent.Executor +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers +import org.mockito.ArgumentMatchers.anyInt +import org.mockito.Captor +import org.mockito.Mock +import org.mockito.Mockito.times +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(Parameterized::class) +class UserTrackerImplReceiveTest : SysuiTestCase() { + + companion object { + + @JvmStatic + @Parameterized.Parameters + fun data(): Iterable<String> = + listOf( + Intent.ACTION_USER_INFO_CHANGED, + Intent.ACTION_MANAGED_PROFILE_AVAILABLE, + Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE, + Intent.ACTION_MANAGED_PROFILE_ADDED, + Intent.ACTION_MANAGED_PROFILE_REMOVED, + Intent.ACTION_MANAGED_PROFILE_UNLOCKED + ) + } + + private val executor: Executor = DirectExecutor.INSTANCE + + @Mock private lateinit var context: Context + @Mock private lateinit var userManager: UserManager + @Mock(stubOnly = true) private lateinit var dumpManager: DumpManager + @Mock(stubOnly = true) private lateinit var handler: Handler + + @Parameterized.Parameter lateinit var intentAction: String + @Mock private lateinit var callback: UserTracker.Callback + @Captor private lateinit var captor: ArgumentCaptor<List<UserInfo>> + + private lateinit var tracker: UserTrackerImpl + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + `when`(context.user).thenReturn(UserHandle.SYSTEM) + `when`(context.createContextAsUser(ArgumentMatchers.any(), anyInt())).thenReturn(context) + + tracker = UserTrackerImpl(context, userManager, dumpManager, handler) + } + + @Test + fun `calls callback and updates profiles when an intent received`() { + tracker.initialize(0) + tracker.addCallback(callback, executor) + val profileID = tracker.userId + 10 + + `when`(userManager.getProfiles(anyInt())).thenAnswer { invocation -> + val id = invocation.getArgument<Int>(0) + val info = UserInfo(id, "", UserInfo.FLAG_FULL) + val infoProfile = + UserInfo( + id + 10, + "", + "", + UserInfo.FLAG_MANAGED_PROFILE, + UserManager.USER_TYPE_PROFILE_MANAGED + ) + infoProfile.profileGroupId = id + listOf(info, infoProfile) + } + + tracker.onReceive(context, Intent(intentAction)) + + verify(callback, times(0)).onUserChanged(anyInt(), any()) + verify(callback, times(1)).onProfilesChanged(capture(captor)) + assertThat(captor.value.map { it.id }).containsExactly(0, profileID) + } +}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt index 52462c7..e65bbb1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
@@ -124,6 +124,16 @@ verify(context).registerReceiverForAllUsers( eq(tracker), capture(captor), isNull(), eq(handler)) + with(captor.value) { + assertThat(countActions()).isEqualTo(7) + assertThat(hasAction(Intent.ACTION_USER_SWITCHED)).isTrue() + assertThat(hasAction(Intent.ACTION_USER_INFO_CHANGED)).isTrue() + assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)).isTrue() + assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)).isTrue() + assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_ADDED)).isTrue() + assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_REMOVED)).isTrue() + assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED)).isTrue() + } } @Test @@ -280,37 +290,6 @@ } @Test - fun testCallbackCalledOnProfileChanged() { - tracker.initialize(0) - val callback = TestCallback() - tracker.addCallback(callback, executor) - val profileID = tracker.userId + 10 - - `when`(userManager.getProfiles(anyInt())).thenAnswer { invocation -> - val id = invocation.getArgument<Int>(0) - val info = UserInfo(id, "", UserInfo.FLAG_FULL) - val infoProfile = UserInfo( - id + 10, - "", - "", - UserInfo.FLAG_MANAGED_PROFILE, - UserManager.USER_TYPE_PROFILE_MANAGED - ) - infoProfile.profileGroupId = id - listOf(info, infoProfile) - } - - val intent = Intent(Intent.ACTION_MANAGED_PROFILE_AVAILABLE) - .putExtra(Intent.EXTRA_USER, UserHandle.of(profileID)) - - tracker.onReceive(context, intent) - - assertThat(callback.calledOnUserChanged).isEqualTo(0) - assertThat(callback.calledOnProfilesChanged).isEqualTo(1) - assertThat(callback.lastUserProfiles.map { it.id }).containsExactly(0, profileID) - } - - @Test fun testCallbackCalledOnUserInfoChanged() { tracker.initialize(0) val callback = TestCallback()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java index 4ccbc6d..091bb54 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNotNull; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doReturn; @@ -74,6 +75,7 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.stubbing.Answer; import java.util.Collections; import java.util.List; @@ -115,8 +117,10 @@ @Spy private PackageManager mPackageManager; private final boolean mIsReduceBrightColorsAvailable = true; - private AutoTileManager mAutoTileManager; + private AutoTileManager mAutoTileManager; // under test + private SecureSettings mSecureSettings; + private ManagedProfileController.Callback mManagedProfileCallback; @Before public void setUp() throws Exception { @@ -303,7 +307,7 @@ InOrder inOrderManagedProfile = inOrder(mManagedProfileController); inOrderManagedProfile.verify(mManagedProfileController).removeCallback(any()); - inOrderManagedProfile.verify(mManagedProfileController, never()).addCallback(any()); + inOrderManagedProfile.verify(mManagedProfileController).addCallback(any()); if (ColorDisplayManager.isNightDisplayAvailable(mContext)) { InOrder inOrderNightDisplay = inOrder(mNightDisplayListener); @@ -504,6 +508,40 @@ } @Test + public void managedProfileAdded_tileAdded() { + when(mAutoAddTracker.isAdded(eq("work"))).thenReturn(false); + mAutoTileManager = createAutoTileManager(mContext); + Mockito.doAnswer((Answer<Object>) invocation -> { + mManagedProfileCallback = invocation.getArgument(0); + return null; + }).when(mManagedProfileController).addCallback(any()); + mAutoTileManager.init(); + when(mManagedProfileController.hasActiveProfile()).thenReturn(true); + + mManagedProfileCallback.onManagedProfileChanged(); + + verify(mQsTileHost, times(1)).addTile(eq("work")); + verify(mAutoAddTracker, times(1)).setTileAdded(eq("work")); + } + + @Test + public void managedProfileRemoved_tileRemoved() { + when(mAutoAddTracker.isAdded(eq("work"))).thenReturn(true); + mAutoTileManager = createAutoTileManager(mContext); + Mockito.doAnswer((Answer<Object>) invocation -> { + mManagedProfileCallback = invocation.getArgument(0); + return null; + }).when(mManagedProfileController).addCallback(any()); + mAutoTileManager.init(); + when(mManagedProfileController.hasActiveProfile()).thenReturn(false); + + mManagedProfileCallback.onManagedProfileChanged(); + + verify(mQsTileHost, times(1)).removeTile(eq("work")); + verify(mAutoAddTracker, times(1)).setTileRemoved(eq("work")); + } + + @Test public void testEmptyArray_doesNotCrash() { mContext.getOrCreateTestableResources().addOverride( R.array.config_quickSettingsAutoAdd, new String[0]);
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java index c131ed6..46b6019 100644 --- a/services/core/java/com/android/server/display/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -554,7 +554,7 @@ /** * Sets the display mode switching type. - * @param newType + * @param newType new mode switching type */ public void setModeSwitchingType(@DisplayManager.SwitchingType int newType) { synchronized (mLock) { @@ -671,6 +671,18 @@ notifyDesiredDisplayModeSpecsChangedLocked(); } + @GuardedBy("mLock") + private float getMaxRefreshRateLocked(int displayId) { + Display.Mode[] modes = mSupportedModesByDisplay.get(displayId); + float maxRefreshRate = 0f; + for (Display.Mode mode : modes) { + if (mode.getRefreshRate() > maxRefreshRate) { + maxRefreshRate = mode.getRefreshRate(); + } + } + return maxRefreshRate; + } + private void notifyDesiredDisplayModeSpecsChangedLocked() { if (mDesiredDisplayModeSpecsListener != null && !mHandler.hasMessages(MSG_REFRESH_RATE_RANGE_CHANGED)) { @@ -989,25 +1001,29 @@ // of low priority voters. It votes [0, max(PEAK, MIN)] public static final int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 7; + // To avoid delay in switching between 60HZ -> 90HZ when activating LHBM, set refresh + // rate to max value (same as for PRIORITY_UDFPS) on lock screen + public static final int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 8; + // LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on. - public static final int PRIORITY_LOW_POWER_MODE = 8; + public static final int PRIORITY_LOW_POWER_MODE = 9; // PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the // higher priority voters' result is a range, it will fix the rate to a single choice. // It's used to avoid refresh rate switches in certain conditions which may result in the // user seeing the display flickering when the switches occur. - public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 9; + public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 10; // Force display to [0, 60HZ] if skin temperature is at or above CRITICAL. - public static final int PRIORITY_SKIN_TEMPERATURE = 10; + public static final int PRIORITY_SKIN_TEMPERATURE = 11; // The proximity sensor needs the refresh rate to be locked in order to function, so this is // set to a high priority. - public static final int PRIORITY_PROXIMITY = 11; + public static final int PRIORITY_PROXIMITY = 12; // The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order // to function, so this needs to be the highest priority of all votes. - public static final int PRIORITY_UDFPS = 12; + public static final int PRIORITY_UDFPS = 13; // Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and // APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString. @@ -1110,6 +1126,8 @@ return "PRIORITY_USER_SETTING_MIN_REFRESH_RATE"; case PRIORITY_USER_SETTING_PEAK_REFRESH_RATE: return "PRIORITY_USER_SETTING_PEAK_REFRESH_RATE"; + case PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE: + return "PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE"; default: return Integer.toString(priority); } @@ -2233,6 +2251,7 @@ private class UdfpsObserver extends IUdfpsHbmListener.Stub { private final SparseBooleanArray mLocalHbmEnabled = new SparseBooleanArray(); + private final SparseBooleanArray mAuthenticationPossible = new SparseBooleanArray(); public void observe() { StatusBarManagerInternal statusBar = @@ -2258,25 +2277,28 @@ private void updateHbmStateLocked(int displayId, boolean enabled) { mLocalHbmEnabled.put(displayId, enabled); - updateVoteLocked(displayId); + updateVoteLocked(displayId, enabled, Vote.PRIORITY_UDFPS); } - private void updateVoteLocked(int displayId) { + @Override + public void onAuthenticationPossible(int displayId, boolean isPossible) { + synchronized (mLock) { + mAuthenticationPossible.put(displayId, isPossible); + updateVoteLocked(displayId, isPossible, + Vote.PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE); + } + } + + @GuardedBy("mLock") + private void updateVoteLocked(int displayId, boolean enabled, int votePriority) { final Vote vote; - if (mLocalHbmEnabled.get(displayId)) { - Display.Mode[] modes = mSupportedModesByDisplay.get(displayId); - float maxRefreshRate = 0f; - for (Display.Mode mode : modes) { - if (mode.getRefreshRate() > maxRefreshRate) { - maxRefreshRate = mode.getRefreshRate(); - } - } + if (enabled) { + float maxRefreshRate = DisplayModeDirector.this.getMaxRefreshRateLocked(displayId); vote = Vote.forRefreshRates(maxRefreshRate, maxRefreshRate); } else { vote = null; } - - DisplayModeDirector.this.updateVoteLocked(displayId, Vote.PRIORITY_UDFPS, vote); + DisplayModeDirector.this.updateVoteLocked(displayId, votePriority, vote); } void dumpLocked(PrintWriter pw) { @@ -2287,6 +2309,13 @@ final String enabled = mLocalHbmEnabled.valueAt(i) ? "enabled" : "disabled"; pw.println(" Display " + displayId + ": " + enabled); } + pw.println(" mAuthenticationPossible: "); + for (int i = 0; i < mAuthenticationPossible.size(); i++) { + final int displayId = mAuthenticationPossible.keyAt(i); + final String isPossible = mAuthenticationPossible.valueAt(i) ? "possible" + : "impossible"; + pw.println(" Display " + displayId + ": " + isPossible); + } } }
diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java index 9a19031..c5fb527 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 @@ 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 java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Collections; import java.util.List; /** @@ -102,15 +104,19 @@ } /** - * Creates a new instance. + * Creates a new instance from a {@link PendingIntent}. * - * @param context context + * <p>This method assumes the session package name has been validated and effectively belongs to + * the media session's owner. + * * @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 @@ } 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 @@ 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 0785fac..1bd5063 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -938,8 +938,7 @@ } @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) @@ -947,7 +946,7 @@ return; } mMediaButtonReceiverHolder = - MediaButtonReceiverHolder.create(mContext, mUserId, pi, sessionPackageName); + MediaButtonReceiverHolder.create(mUserId, pi, mPackageName); mService.onMediaButtonReceiverChanged(MediaSessionRecord.this); } finally { Binder.restoreCallingIdentity(token);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index b89147e..d08150c 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -2285,9 +2285,9 @@ PendingIntent pi = mCustomMediaKeyDispatcher.getMediaButtonReceiver(keyEvent, uid, asSystemService); if (pi != null) { - mediaButtonReceiverHolder = MediaButtonReceiverHolder.create(mContext, - mCurrentFullUserRecord.mFullUserId, pi, - /* sessionPackageName= */ ""); + mediaButtonReceiverHolder = + MediaButtonReceiverHolder.create( + mCurrentFullUserRecord.mFullUserId, pi, ""); } } }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 1ea949e..2f818fa 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -123,6 +123,7 @@ import static android.telephony.CarrierConfigManager.KEY_DATA_WARNING_NOTIFICATION_BOOL; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; +import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; import static com.android.internal.util.ArrayUtils.appendInt; import static com.android.internal.util.XmlUtils.readBooleanAttribute; import static com.android.internal.util.XmlUtils.readIntAttribute; @@ -3148,7 +3149,8 @@ * active merge set [A,B], we'd return a new template that primarily matches * A, but also matches B. */ - private static NetworkTemplate normalizeTemplate(@NonNull NetworkTemplate template, + @VisibleForTesting(visibility = PRIVATE) + static NetworkTemplate normalizeTemplate(@NonNull NetworkTemplate template, @NonNull List<String[]> mergedList) { // Now there are several types of network which uses Subscriber Id to store network // information. For instance: @@ -3158,6 +3160,12 @@ if (template.getSubscriberIds().isEmpty()) return template; for (final String[] merged : mergedList) { + // In some rare cases (e.g. b/243015487), merged subscriberId list might contain + // duplicated items. Deduplication for better error handling. + final ArraySet mergedSet = new ArraySet(merged); + if (mergedSet.size() != merged.length) { + Log.wtf(TAG, "Duplicated merged list detected: " + Arrays.toString(merged)); + } // TODO: Handle incompatible subscriberIds if that happens in practice. for (final String subscriberId : template.getSubscriberIds()) { if (com.android.net.module.util.CollectionUtils.contains(merged, subscriberId)) { @@ -3165,7 +3173,7 @@ // a template that matches all merged subscribers. return new NetworkTemplate.Builder(template.getMatchRule()) .setWifiNetworkKeys(template.getWifiNetworkKeys()) - .setSubscriberIds(Set.of(merged)) + .setSubscriberIds(mergedSet) .setMeteredness(template.getMeteredness()) .build(); }
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java index fb0cdfa..b96c1d0 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -1939,6 +1939,74 @@ new int[]{20}); } + @Test + public void testAuthenticationPossibleSetsPhysicalRateRangesToMax() throws RemoteException { + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); + // don't call director.start(createMockSensorManager()); + // DisplayObserver will reset mSupportedModesByDisplay + director.onBootCompleted(); + ArgumentCaptor<IUdfpsHbmListener> captor = + ArgumentCaptor.forClass(IUdfpsHbmListener.class); + verify(mStatusBarMock).setUdfpsHbmListener(captor.capture()); + + captor.getValue().onAuthenticationPossible(DISPLAY_ID, true); + + Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE); + assertThat(vote.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90); + assertThat(vote.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90); + } + + @Test + public void testAuthenticationPossibleUnsetsVote() throws RemoteException { + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); + director.start(createMockSensorManager()); + director.onBootCompleted(); + ArgumentCaptor<IUdfpsHbmListener> captor = + ArgumentCaptor.forClass(IUdfpsHbmListener.class); + verify(mStatusBarMock).setUdfpsHbmListener(captor.capture()); + captor.getValue().onAuthenticationPossible(DISPLAY_ID, true); + captor.getValue().onAuthenticationPossible(DISPLAY_ID, false); + + Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE); + assertNull(vote); + } + + @Test + public void testUdfpsRequestSetsPhysicalRateRangesToMax() throws RemoteException { + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); + // don't call director.start(createMockSensorManager()); + // DisplayObserver will reset mSupportedModesByDisplay + director.onBootCompleted(); + ArgumentCaptor<IUdfpsHbmListener> captor = + ArgumentCaptor.forClass(IUdfpsHbmListener.class); + verify(mStatusBarMock).setUdfpsHbmListener(captor.capture()); + + captor.getValue().onHbmEnabled(DISPLAY_ID); + + Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_UDFPS); + assertThat(vote.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90); + assertThat(vote.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90); + } + + @Test + public void testUdfpsRequestUnsetsUnsetsVote() throws RemoteException { + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); + director.start(createMockSensorManager()); + director.onBootCompleted(); + ArgumentCaptor<IUdfpsHbmListener> captor = + ArgumentCaptor.forClass(IUdfpsHbmListener.class); + verify(mStatusBarMock).setUdfpsHbmListener(captor.capture()); + captor.getValue().onHbmEnabled(DISPLAY_ID); + captor.getValue().onHbmEnabled(DISPLAY_ID); + + Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_UDFPS); + assertNull(vote); + } + private Temperature getSkinTemp(@Temperature.ThrottlingStatus int status) { return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status); }
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java index 07009cb..7c7e2ee 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -75,6 +75,7 @@ import static com.android.server.net.NetworkPolicyManagerService.TYPE_RAPID; import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING; import static com.android.server.net.NetworkPolicyManagerService.UidBlockedState.getEffectiveBlockedReasons; +import static com.android.server.net.NetworkPolicyManagerService.normalizeTemplate; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -2059,6 +2060,18 @@ METERED_NO, actualPolicy.template.getMeteredness()); } + @Test + public void testNormalizeTemplate_duplicatedMergedImsiList() { + final NetworkTemplate template = new NetworkTemplate.Builder(MATCH_CARRIER) + .setSubscriberIds(Set.of(TEST_IMSI)).build(); + final String[] mergedImsiGroup = new String[] {TEST_IMSI, TEST_IMSI}; + final ArrayList<String[]> mergedList = new ArrayList<>(); + mergedList.add(mergedImsiGroup); + // Verify the duplicated items in the merged IMSI list won't crash the system. + final NetworkTemplate result = normalizeTemplate(template, mergedList); + assertEquals(template, result); + } + private String formatBlockedStateError(int uid, int rule, boolean metered, boolean backgroundRestricted) { return String.format(