summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/tests/coretests/src/android/app/KeyguardManagerTest.java38
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java15
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java12
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt1
-rw-r--r--packages/SystemUI/res-keyguard/values/strings.xml6
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java56
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt93
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java2
-rw-r--r--services/core/java/com/android/server/am/CachedAppOptimizer.java115
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java5
-rw-r--r--services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java16
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java7
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java222
-rw-r--r--services/core/java/com/android/server/audio/BtHelper.java2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java29
29 files changed, 455 insertions, 293 deletions
diff --git a/core/tests/coretests/src/android/app/KeyguardManagerTest.java b/core/tests/coretests/src/android/app/KeyguardManagerTest.java
index 7231fbd3b7eb..958906c36d05 100644
--- a/core/tests/coretests/src/android/app/KeyguardManagerTest.java
+++ b/core/tests/coretests/src/android/app/KeyguardManagerTest.java
@@ -19,6 +19,7 @@ package android.app;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
@@ -26,6 +27,7 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -209,6 +211,42 @@ public class KeyguardManagerTest {
verifyDeviceLockedAndRemoveLock();
}
+ @Test
+ public void createConfirmDeviceCredentialForRemoteValidationIntent() {
+ RemoteLockscreenValidationSession remoteLockscreenValidationSession =
+ new RemoteLockscreenValidationSession.Builder()
+ .setSourcePublicKey("sourcePublicKey".getBytes())
+ .build();
+ ComponentName componentName = new ComponentName("pkg", "cls");
+ String title = "title";
+ String description = "description";
+ String checkboxLabel = "checkboxLabel";
+ String alternateButtonLabel = "alternateButtonLabel";
+
+ Intent intent = mKeyguardManager.createConfirmDeviceCredentialForRemoteValidationIntent(
+ remoteLockscreenValidationSession,
+ componentName,
+ title,
+ description,
+ checkboxLabel,
+ alternateButtonLabel
+ );
+
+ assertNotNull(intent);
+ assertEquals(KeyguardManager.ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL, intent.getAction());
+ assertEquals(remoteLockscreenValidationSession,
+ intent.getParcelableExtra(
+ KeyguardManager.EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION,
+ RemoteLockscreenValidationSession.class));
+ assertEquals(componentName,
+ intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME, ComponentName.class));
+ assertEquals(title, intent.getStringExtra(KeyguardManager.EXTRA_TITLE));
+ assertEquals(description, intent.getStringExtra(KeyguardManager.EXTRA_DESCRIPTION));
+ assertEquals(checkboxLabel, intent.getStringExtra(KeyguardManager.EXTRA_CHECKBOX_LABEL));
+ assertEquals(alternateButtonLabel,
+ intent.getStringExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL));
+ }
+
private void verifyDeviceLockedAndRemoveLock() {
assertTrue(mKeyguardManager.isDeviceSecure());
assertTrue("Failed to remove new password that was set in the test case.",
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
index f9aa1bd98e38..1e6e50359cf3 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
@@ -239,7 +239,7 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
// display state, so we have to look through all displays to match the address
final Display[] displays = mDisplayManager.getDisplays(
DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
- final Display defaultDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+
for (int i = 0; i < displays.length; i++) {
DisplayAddress.Physical address =
@@ -255,6 +255,8 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
// TODO(b/287170025): This should be something like if (!rearDisplay.isEnabled)
// instead. Currently when the rear display is disabled, its state is STATE_OFF.
if (rearDisplay.getDisplayId() != Display.DEFAULT_DISPLAY) {
+ final Display defaultDisplay = mDisplayManager
+ .getDisplay(Display.DEFAULT_DISPLAY);
rotateRearDisplayMetricsIfNeeded(defaultDisplay.getRotation(),
rearDisplay.getRotation(), rearDisplayMetrics);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index acbdbf9d6769..cff317259f1e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -710,4 +710,19 @@ public abstract class WMShellModule {
static DesktopModeTaskRepository provideDesktopModeTaskRepository() {
return new DesktopModeTaskRepository();
}
+
+ //
+ // Misc
+ //
+
+ // TODO: Temporarily move dependencies to this instead of ShellInit since that is needed to add
+ // the callback. We will be moving to a different explicit startup mechanism in a follow- up CL.
+ @WMSingleton
+ @ShellCreateTriggerOverride
+ @Provides
+ static Object provideIndependentShellComponentsToCreate(
+ DefaultMixedHandler defaultMixedHandler,
+ Optional<DesktopModeController> desktopModeController) {
+ return new Object();
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index da14d03adb35..964ba9f9aa7c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -2365,6 +2365,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, out);
}
}
+
+ // When split in the background, it should be only opening/dismissing transition and
+ // would keep out not empty. Prevent intercepting all transitions for split screen when
+ // it is in the background and not identify to handle it.
+ return (!out.isEmpty() || isSplitScreenVisible()) ? out : null;
} else {
if (isOpening && getStageOfTask(triggerTask) != null) {
// One task is appearing into split, prepare to enter split screen.
@@ -2373,8 +2378,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSplitTransitions.setEnterTransition(transition, request.getRemoteTransition(),
TRANSIT_SPLIT_SCREEN_PAIR_OPEN, !mIsDropEntering);
}
+ return out;
}
- return out;
}
/**
@@ -2506,8 +2511,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
&& getStageType(dismissStages.valueAt(0)) == STAGE_TYPE_MAIN)
|| mMainStage.getChildCount() == 0 ? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN;
// If there is a fullscreen opening change, we should not bring stage to top.
- prepareExitSplitScreen(record.mContainShowFullscreenChange
- ? STAGE_TYPE_UNDEFINED : dismissTop, wct);
+ prepareExitSplitScreen(
+ !record.mContainShowFullscreenChange && isSplitScreenVisible()
+ ? dismissTop : STAGE_TYPE_UNDEFINED, wct);
mSplitTransitions.startDismissTransition(wct, this, dismissTop,
EXIT_REASON_APP_FINISHED);
// This can happen in some pathological cases. For example:
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index 8cba2ab0b70b..702cc05f7f5f 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -56,7 +56,6 @@ private val KNOWN_PLUGINS =
"com.android.systemui.falcon.four" to listOf(ClockMetadata("DIGITAL_CLOCK_GROWTH")),
"com.android.systemui.falcon.five" to listOf(ClockMetadata("DIGITAL_CLOCK_HANDWRITTEN")),
"com.android.systemui.falcon.six" to listOf(ClockMetadata("DIGITAL_CLOCK_INFLATE")),
- "com.android.systemui.falcon.seven" to listOf(ClockMetadata("DIGITAL_CLOCK_METRO")),
"com.android.systemui.falcon.eight" to listOf(ClockMetadata("DIGITAL_CLOCK_NUMBEROVERLAP")),
"com.android.systemui.falcon.nine" to listOf(ClockMetadata("DIGITAL_CLOCK_WEATHER")),
)
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 28f5f3d9edd7..badad584824b 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -358,12 +358,12 @@
<!-- Message shown to prepare for an unattended update (OTA). Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] -->
<string name="kg_prompt_unattended_update_pattern">Draw pattern to install update later</string>
- <!-- Message shown after an unattended update (OTA) asking the user to enter their PIN. Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] -->
+ <!-- Message shown after an unattended mainline (major) update asking the user to enter their PIN. [CHAR LIMIT=70] -->
<string name="kg_prompt_after_update_pin">Device updated. Enter PIN to continue.</string>
- <!-- Message shown after an unattended update (OTA) asking the user to enter their password. Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] -->
+ <!-- Message shown after an unattended mainline (major) update asking the user to enter their password. [CHAR LIMIT=70] -->
<string name="kg_prompt_after_update_password">Device updated. Enter password to continue.</string>
- <!-- Message shown after an unattended update (OTA) asking the user to enter their pattern. Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] -->
+ <!-- Message shown after an unattended mainline (major) update asking the user to enter their pattern. [CHAR LIMIT=70] -->
<string name="kg_prompt_after_update_pattern">Device updated. Draw pattern to continue.</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 7a0a24a85eaf..03d9eb3455fd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -23,6 +23,7 @@ import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART;
+import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
@@ -99,6 +100,8 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView {
switch (reason) {
case PROMPT_REASON_RESTART:
return R.string.kg_prompt_reason_restart_password;
+ case PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE:
+ return R.string.kg_prompt_after_update_password;
case PROMPT_REASON_TIMEOUT:
return R.string.kg_prompt_reason_timeout_password;
case PROMPT_REASON_DEVICE_ADMIN:
@@ -106,7 +109,7 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView {
case PROMPT_REASON_USER_REQUEST:
return R.string.kg_prompt_after_user_lockdown_password;
case PROMPT_REASON_PREPARE_FOR_UPDATE:
- return R.string.kg_prompt_reason_timeout_password;
+ return R.string.kg_prompt_unattended_update_password;
case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT:
return R.string.kg_prompt_reason_timeout_password;
case PROMPT_REASON_TRUSTAGENT_EXPIRED:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index be423767e6d0..3d255a58cf8e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -304,6 +304,9 @@ public class KeyguardPatternViewController
case PROMPT_REASON_RESTART:
resId = R.string.kg_prompt_reason_restart_pattern;
break;
+ case PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE:
+ resId = R.string.kg_prompt_after_update_pattern;
+ break;
case PROMPT_REASON_TIMEOUT:
resId = R.string.kg_prompt_reason_timeout_pattern;
break;
@@ -314,7 +317,7 @@ public class KeyguardPatternViewController
resId = R.string.kg_prompt_after_user_lockdown_pattern;
break;
case PROMPT_REASON_PREPARE_FOR_UPDATE:
- resId = R.string.kg_prompt_reason_timeout_pattern;
+ resId = R.string.kg_prompt_unattended_update_pattern;
break;
case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT:
resId = R.string.kg_prompt_reason_timeout_pattern;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 687436c5d388..38e5dc57d316 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -21,6 +21,7 @@ import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART;
+import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
@@ -113,6 +114,8 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
switch (reason) {
case PROMPT_REASON_RESTART:
return R.string.kg_prompt_reason_restart_pin;
+ case PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE:
+ return R.string.kg_prompt_after_update_pin;
case PROMPT_REASON_TIMEOUT:
return R.string.kg_prompt_reason_timeout_pin;
case PROMPT_REASON_DEVICE_ADMIN:
@@ -120,7 +123,7 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
case PROMPT_REASON_USER_REQUEST:
return R.string.kg_prompt_after_user_lockdown_pin;
case PROMPT_REASON_PREPARE_FOR_UPDATE:
- return R.string.kg_prompt_reason_timeout_pin;
+ return R.string.kg_prompt_unattended_update_pin;
case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT:
return R.string.kg_prompt_reason_timeout_pin;
case PROMPT_REASON_TRUSTAGENT_EXPIRED:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
index 419303d71f97..21960e219fc9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
@@ -103,6 +103,12 @@ public interface KeyguardSecurityView {
int PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT = 15;
/**
+ * Strong auth is required because the device has just booted because of an automatic
+ * mainline update.
+ */
+ int PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE = 16;
+
+ /**
* Reset the view and prepare to take input. This should do things like clearing the
* password or pattern and clear error messages.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 3f2054029459..10cacb201c29 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -740,6 +740,12 @@ object Flags {
val ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD =
releasedFlag(2900, "zj_285570694_lockscreen_transition_from_aod")
+ // 3000 - dream
+ // TODO(b/285059790) : Tracking Bug
+ @JvmField
+ val LOCKSCREEN_WALLPAPER_DREAM_ENABLED =
+ unreleasedFlag(3000, name = "enable_lockscreen_wallpaper_dream")
+
// TODO(b/283084712): Tracking Bug
@JvmField
val IMPROVED_HUN_ANIMATIONS = unreleasedFlag(283084712, "improved_hun_animations")
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index a2c940bd298c..e6053fb3e352 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -80,6 +80,8 @@ import com.android.wm.shell.util.CounterRotator;
import com.android.wm.shell.util.TransitionUtil;
import java.util.ArrayList;
+import java.util.Map;
+import java.util.WeakHashMap;
import javax.inject.Inject;
@@ -192,7 +194,8 @@ public class KeyguardService extends Service {
private final CounterRotator mCounterRotator = new CounterRotator();
@GuardedBy("mLeashMap")
- private IRemoteTransitionFinishedCallback mFinishCallback = null;
+ private final Map<IBinder, IRemoteTransitionFinishedCallback> mFinishCallbacks =
+ new WeakHashMap<>();
@Override
public void startAnimation(IBinder transition, TransitionInfo info,
@@ -206,7 +209,7 @@ public class KeyguardService extends Service {
synchronized (mLeashMap) {
apps = wrap(info, false /* wallpapers */, t, mLeashMap, mCounterRotator);
wallpapers = wrap(info, true /* wallpapers */, t, mLeashMap, mCounterRotator);
- mFinishCallback = finishCallback;
+ mFinishCallbacks.put(transition, finishCallback);
}
// Set alpha back to 1 for the independent changes because we will be animating
@@ -229,7 +232,7 @@ public class KeyguardService extends Service {
@Override
public void onAnimationFinished() throws RemoteException {
Slog.d(TAG, "Finish IRemoteAnimationRunner.");
- finish();
+ finish(transition);
}
});
}
@@ -246,7 +249,7 @@ public class KeyguardService extends Service {
try {
runner.onAnimationCancelled();
- finish();
+ finish(currentTransition);
} catch (RemoteException e) {
// nothing, we'll just let it finish on its own I guess.
}
@@ -260,7 +263,7 @@ public class KeyguardService extends Service {
}
}
- private void finish() throws RemoteException {
+ private void finish(IBinder transition) throws RemoteException {
IRemoteTransitionFinishedCallback finishCallback = null;
SurfaceControl.Transaction finishTransaction = null;
@@ -271,8 +274,7 @@ public class KeyguardService extends Service {
mCounterRotator.cleanUp(finishTransaction);
}
mLeashMap.clear();
- finishCallback = mFinishCallback;
- mFinishCallback = null;
+ finishCallback = mFinishCallbacks.remove(transition);
}
if (finishCallback != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 5bf56a1da32f..ff62aea10e5b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -137,6 +137,7 @@ import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
+import com.android.systemui.flags.SystemPropertiesHelper;
import com.android.systemui.keyguard.dagger.KeyguardModule;
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
import com.android.systemui.log.SessionTracker;
@@ -167,6 +168,7 @@ import dagger.Lazy;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -280,6 +282,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
* keyguard to show even if it is disabled for the current user.
*/
public static final String OPTION_FORCE_SHOW = "force_show";
+ public static final String SYS_BOOT_REASON_PROP = "sys.boot.reason.last";
+ public static final String REBOOT_MAINLINE_UPDATE = "reboot,mainline_update";
private final DreamOverlayStateController mDreamOverlayStateController;
/** The stream type that the lock sounds are tied to. */
@@ -315,6 +319,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
/** UserSwitcherController for creating guest user on boot complete */
private final UserSwitcherController mUserSwitcherController;
+ private SystemPropertiesHelper mSystemPropertiesHelper;
/**
* Used to keep the device awake while to ensure the keyguard finishes opening before
@@ -846,7 +851,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
strongAuthTracker.isNonStrongBiometricAllowedAfterIdleTimeout(currentUser);
if (any && !strongAuthTracker.hasUserAuthenticatedSinceBoot()) {
- return KeyguardSecurityView.PROMPT_REASON_RESTART;
+ String reasonForReboot = mSystemPropertiesHelper.get(SYS_BOOT_REASON_PROP);
+ if (Objects.equals(reasonForReboot, REBOOT_MAINLINE_UPDATE)) {
+ return KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE;
+ } else {
+ return KeyguardSecurityView.PROMPT_REASON_RESTART;
+ }
} else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_TIMEOUT) != 0) {
return KeyguardSecurityView.PROMPT_REASON_TIMEOUT;
} else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN) != 0) {
@@ -1304,7 +1314,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
Lazy<ScrimController> scrimControllerLazy,
FeatureFlags featureFlags,
@Main CoroutineDispatcher mainDispatcher,
- Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel) {
+ Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel,
+ SystemPropertiesHelper systemPropertiesHelper) {
mContext = context;
mUserTracker = userTracker;
mFalsingCollector = falsingCollector;
@@ -1318,6 +1329,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
mPM = powerManager;
mTrustManager = trustManager;
mUserSwitcherController = userSwitcherController;
+ mSystemPropertiesHelper = systemPropertiesHelper;
mStatusBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mKeyguardDisplayManager = keyguardDisplayManager;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index ab79c8067cd5..1f121e92d7d0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -42,6 +42,7 @@ import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.SystemPropertiesHelper;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -134,7 +135,8 @@ public class KeyguardModule {
Lazy<ScrimController> scrimControllerLazy,
FeatureFlags featureFlags,
@Main CoroutineDispatcher mainDispatcher,
- Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel) {
+ Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel,
+ SystemPropertiesHelper systemPropertiesHelper) {
return new KeyguardViewMediator(
context,
uiEventLogger,
@@ -170,7 +172,8 @@ public class KeyguardModule {
scrimControllerLazy,
featureFlags,
mainDispatcher,
- dreamingToLockscreenTransitionViewModel);
+ dreamingToLockscreenTransitionViewModel,
+ systemPropertiesHelper);
}
/** */
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index b96ca7ac2961..3b32313e76a0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -224,7 +224,6 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
return LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION;
}
});
- controller.overrideIconTintForNavMode(true);
return controller;
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index d2e94d6a20a5..776a90d75a75 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -4813,7 +4813,9 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && mQsController.handleTouch(
event, isFullyCollapsed(), isShadeOrQsHeightAnimationRunning())) {
- mShadeLog.logMotionEvent(event, "onTouch: handleQsTouch handled event");
+ if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
+ mShadeLog.logMotionEvent(event, "onTouch: handleQsTouch handled event");
+ }
return true;
}
if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
@@ -4827,7 +4829,6 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
}
handled |= handleTouch(event);
- mShadeLog.logOnTouchEventLastReturn(event, !mDozing, handled);
return !mDozing || handled;
}
@@ -5010,7 +5011,6 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
}
break;
}
- mShadeLog.logHandleTouchLastReturn(event, !mGestureWaitForTouchSlop, mTracking);
return !mGestureWaitForTouchSlop || mTracking;
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index 6480164cdaf5..62e79112a1d1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -1186,7 +1186,6 @@ public class QuickSettingsController implements Dumpable {
mClippingAnimationEndBounds.left, fraction);
int animTop = (int) MathUtils.lerp(startTop,
mClippingAnimationEndBounds.top, fraction);
- logClippingTopBound("interpolated top bound", top);
int animRight = (int) MathUtils.lerp(startRight,
mClippingAnimationEndBounds.right, fraction);
int animBottom = (int) MathUtils.lerp(startBottom,
@@ -1337,8 +1336,6 @@ public class QuickSettingsController implements Dumpable {
// the screen without clipping.
return -mAmbientState.getStackTopMargin();
} else {
- logNotificationsClippingTopBound(qsTop,
- mNotificationStackScrollLayoutController.getTop());
return qsTop - mNotificationStackScrollLayoutController.getTop();
}
}
@@ -1380,25 +1377,21 @@ public class QuickSettingsController implements Dumpable {
keyguardNotificationStaticPadding, maxQsPadding) : maxQsPadding;
topPadding = (int) MathUtils.lerp((float) getMinExpansionHeight(),
(float) max, expandedFraction);
- logNotificationsTopPadding("keyguard and expandImmediate", topPadding);
return topPadding;
} else if (isSizeChangeAnimationRunning()) {
topPadding = Math.max((int) mSizeChangeAnimator.getAnimatedValue(),
keyguardNotificationStaticPadding);
- logNotificationsTopPadding("size change animation running", topPadding);
return topPadding;
} else if (keyguardShowing) {
// We can only do the smoother transition on Keyguard when we also are not collapsing
// from a scrolled quick settings.
topPadding = MathUtils.lerp((float) keyguardNotificationStaticPadding,
(float) (getMaxExpansionHeight()), computeExpansionFraction());
- logNotificationsTopPadding("keyguard", topPadding);
return topPadding;
} else {
topPadding = Math.max(mQsFrameTranslateController.getNotificationsTopPadding(
mExpansionHeight, mNotificationStackScrollLayoutController),
mQuickQsHeaderHeight);
- logNotificationsTopPadding("default case", topPadding);
return topPadding;
}
}
@@ -1446,38 +1439,6 @@ public class QuickSettingsController implements Dumpable {
- mAmbientState.getScrollY());
}
- /** TODO(b/273591201): remove after bug resolved */
- private void logNotificationsTopPadding(String message, float rawPadding) {
- int padding = ((int) rawPadding / 10) * 10;
- if (mBarState != KEYGUARD && padding != mLastNotificationsTopPadding && !mExpanded) {
- mLastNotificationsTopPadding = padding;
- mShadeLog.logNotificationsTopPadding(message, padding);
- }
- }
-
- /** TODO(b/273591201): remove after bug resolved */
- private void logClippingTopBound(String message, int top) {
- top = (top / 10) * 10;
- if (mBarState != KEYGUARD && mShadeExpandedFraction == 1
- && top != mLastClippingTopBound && !mExpanded) {
- mLastClippingTopBound = top;
- mShadeLog.logClippingTopBound(message, top);
- }
- }
-
- /** TODO(b/273591201): remove after bug resolved */
- private void logNotificationsClippingTopBound(int top, int nsslTop) {
- top = (top / 10) * 10;
- nsslTop = (nsslTop / 10) * 10;
- if (mBarState == SHADE && mShadeExpandedFraction == 1
- && (top != mLastNotificationsClippingTopBound
- || nsslTop != mLastNotificationsClippingTopBoundNssl) && !mExpanded) {
- mLastNotificationsClippingTopBound = top;
- mLastNotificationsClippingTopBoundNssl = nsslTop;
- mShadeLog.logNotificationsClippingTopBound(top, nsslTop);
- }
- }
-
private int calculateTopClippingBound(int qsPanelBottomY) {
int top;
if (mSplitShadeEnabled) {
@@ -1487,7 +1448,6 @@ public class QuickSettingsController implements Dumpable {
// If we're transitioning, let's use the actual value. The else case
// can be wrong during transitions when waiting for the keyguard to unlock
top = mTransitionToFullShadePosition;
- logClippingTopBound("set while transitioning to full shade", top);
} else {
final float notificationTop = getEdgePosition();
if (mBarState == KEYGUARD) {
@@ -1496,10 +1456,8 @@ public class QuickSettingsController implements Dumpable {
// this should go away once we unify the stackY position and don't have
// to do this min anymore below.
top = qsPanelBottomY;
- logClippingTopBound("bypassing keyguard", top);
} else {
top = (int) Math.min(qsPanelBottomY, notificationTop);
- logClippingTopBound("keyguard default case", top);
}
} else {
top = (int) notificationTop;
@@ -1507,14 +1465,12 @@ public class QuickSettingsController implements Dumpable {
}
// TODO (b/265193930): remove dependency on NPVC
top += mPanelViewControllerLazy.get().getOverStretchAmount();
- logClippingTopBound("including overstretch", top);
// Correction for instant expansion caused by HUN pull down/
float minFraction = mPanelViewControllerLazy.get().getMinFraction();
if (minFraction > 0f && minFraction < 1f) {
float realFraction = (mShadeExpandedFraction
- minFraction) / (1f - minFraction);
top *= MathUtils.saturate(realFraction / minFraction);
- logClippingTopBound("after adjusted fraction", top);
}
}
return top;
@@ -1654,15 +1610,11 @@ public class QuickSettingsController implements Dumpable {
// as sometimes the qsExpansionFraction can be a tiny value instead of 0 when in QQS.
if (!mSplitShadeEnabled && !mLastShadeFlingWasExpanding
&& computeExpansionFraction() <= 0.01 && mShadeExpandedFraction < 1.0) {
- mShadeLog.logMotionEvent(event,
- "handleQsTouch: shade touched while shade collapsing, QS tracking disabled");
mTracking = false;
}
if (!isExpandImmediate() && mTracking) {
onTouch(event);
if (!mConflictingExpansionGesture && !mSplitShadeEnabled) {
- mShadeLog.logMotionEvent(event,
- "handleQsTouch: not immediate expand or conflicting gesture");
return true;
}
}
@@ -1756,7 +1708,6 @@ public class QuickSettingsController implements Dumpable {
break;
case MotionEvent.ACTION_MOVE:
- mShadeLog.logMotionEvent(event, "onQsTouch: move action, setting QS expansion");
setExpansionHeight(h + mInitialHeightOnTouch);
// TODO (b/265193930): remove dependency on NPVC
if (h >= mPanelViewControllerLazy.get().getFalsingThreshold()) {
@@ -1844,17 +1795,14 @@ public class QuickSettingsController implements Dumpable {
final float h = y - mInitialTouchY;
trackMovement(event);
if (mTracking) {
-
// Already tracking because onOverscrolled was called. We need to update here
// so we don't stop for a frame until the next touch event gets handled in
// onTouchEvent.
setExpansionHeight(h + mInitialHeightOnTouch);
trackMovement(event);
return true;
- } else {
- mShadeLog.logMotionEvent(event,
- "onQsIntercept: move ignored because qs tracking disabled");
}
+
// TODO (b/265193930): remove dependency on NPVC
float touchSlop = event.getClassification()
== MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE
@@ -1878,7 +1826,7 @@ public class QuickSettingsController implements Dumpable {
} else {
mShadeLog.logQsTrackingNotStarted(mInitialTouchY, y, h, touchSlop,
getExpanded(), mPanelViewControllerLazy.get().isKeyguardShowing(),
- isExpansionEnabled());
+ isExpansionEnabled(), event.getDownTime());
}
break;
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
index 2b772e372f77..2da8d5f4d921 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
@@ -54,7 +54,8 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) {
touchSlop: Float,
qsExpanded: Boolean,
keyguardShowing: Boolean,
- qsExpansionEnabled: Boolean
+ qsExpansionEnabled: Boolean,
+ downTime: Long
) {
buffer.log(
TAG,
@@ -67,10 +68,11 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) {
bool1 = qsExpanded
bool2 = keyguardShowing
bool3 = qsExpansionEnabled
+ str1 = downTime.toString()
},
{
- "QsTrackingNotStarted: initTouchY=$int1,y=$int2,h=$long1,slop=$double1,qsExpanded" +
- "=$bool1,keyguardShowing=$bool2,qsExpansion=$bool3"
+ "QsTrackingNotStarted: downTime=$str1,initTouchY=$int1,y=$int2,h=$long1," +
+ "slop=$double1,qsExpanded=$bool1,keyguardShowing=$bool2,qsExpansion=$bool3"
}
)
}
@@ -306,91 +308,6 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) {
)
}
- fun logNotificationsTopPadding(message: String, padding: Int) {
- buffer.log(
- TAG,
- LogLevel.VERBOSE,
- {
- str1 = message
- int1 = padding
- },
- { "QSC NotificationsTopPadding $str1: $int1"}
- )
- }
-
- fun logClippingTopBound(message: String, top: Int) {
- buffer.log(
- TAG,
- LogLevel.VERBOSE,
- {
- str1 = message
- int1 = top
- },
- { "QSC ClippingTopBound $str1: $int1" }
- )
- }
-
- fun logNotificationsClippingTopBound(top: Int, nsslTop: Int) {
- buffer.log(
- TAG,
- LogLevel.VERBOSE,
- {
- int1 = top
- int2 = nsslTop
- },
- { "QSC NotificationsClippingTopBound set to $int1 - $int2" }
- )
- }
-
- fun logOnTouchEventLastReturn(
- event: MotionEvent,
- dozing: Boolean,
- handled: Boolean,
- ) {
- buffer.log(
- TAG,
- LogLevel.VERBOSE,
- {
- bool1 = dozing
- bool2 = handled
- long1 = event.eventTime
- long2 = event.downTime
- int1 = event.action
- int2 = event.classification
- double1 = event.y.toDouble()
- },
- {
- "NPVC onTouchEvent last return: !mDozing: $bool1 || handled: $bool2 " +
- "\neventTime=$long1,downTime=$long2,y=$double1,action=$int1,class=$int2"
- }
- )
- }
-
- fun logHandleTouchLastReturn(
- event: MotionEvent,
- gestureWaitForTouchSlop: Boolean,
- tracking: Boolean,
- ) {
- buffer.log(
- TAG,
- LogLevel.VERBOSE,
- {
- bool1 = gestureWaitForTouchSlop
- bool2 = tracking
- long1 = event.eventTime
- long2 = event.downTime
- int1 = event.action
- int2 = event.classification
- double1 = event.y.toDouble()
- },
- {
- "NPVC handleTouch last return: !mGestureWaitForTouchSlop: $bool1 " +
- "|| mTracking: $bool2 " +
- "\neventTime=$long1,downTime=$long2,y=$double1,action=$int1,class=$int2"
- }
- )
- }
-
fun logUpdateNotificationPanelTouchState(
disabled: Boolean,
isGoingToSleep: Boolean,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 1cd0f081a744..648ece527bef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -475,6 +475,13 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
*/
private boolean mShouldDelayWakeUpAnimation = false;
+ /**
+ * Whether we should delay the AOD->Lockscreen animation.
+ * If false, the animation will start in onStartedWakingUp().
+ * If true, the animation will start in onFinishedWakingUp().
+ */
+ private boolean mShouldDelayLockscreenTransitionFromAod = false;
+
private final Object mQueueLock = new Object();
private final PulseExpansionHandler mPulseExpansionHandler;
@@ -3242,7 +3249,10 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
updateVisibleToUser();
updateIsKeyguard();
- if (!mFeatureFlags.isEnabled(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD)) {
+ mShouldDelayLockscreenTransitionFromAod = mDozeParameters.getAlwaysOn()
+ && mFeatureFlags.isEnabled(
+ Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD);
+ if (!mShouldDelayLockscreenTransitionFromAod) {
startLockscreenTransitionFromAod();
}
});
@@ -3251,8 +3261,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
/**
* Private helper for starting the LOCKSCREEN_TRANSITION_FROM_AOD animation - only necessary
- * so we can start it from either onFinishedWakingUp() or onFinishedWakingUp() depending
- * on a flag value.
+ * so we can start it from either onFinishedWakingUp() or onFinishedWakingUp().
*/
private void startLockscreenTransitionFromAod() {
// stopDozing() starts the LOCKSCREEN_TRANSITION_FROM_AOD animation.
@@ -3273,7 +3282,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
@Override
public void onFinishedWakingUp() {
- if (mFeatureFlags.isEnabled(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD)) {
+ if (mShouldDelayLockscreenTransitionFromAod) {
mNotificationShadeWindowController.batchApplyWindowLayoutParams(
this::startLockscreenTransitionFromAod);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 7bc4fc3c5e47..ae70384aa71a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -115,7 +115,6 @@ public class LightBarTransitionsController implements Dumpable {
};
private final Context mContext;
- private Boolean mOverrideIconTintForNavMode;
@AssistedInject
public LightBarTransitionsController(
@@ -276,19 +275,11 @@ public class LightBarTransitionsController implements Dumpable {
}
/**
- * Specify an override value to return for {@link #overrideIconTintForNavMode(boolean)}.
- */
- public void overrideIconTintForNavMode(boolean overrideValue) {
- mOverrideIconTintForNavMode = overrideValue;
- }
- /**
* Return whether to use the tint calculated in this class for nav icons.
*/
public boolean supportsIconTintForNavMode(int navigationMode) {
// In gesture mode, we already do region sampling to update tint based on content beneath.
- return mOverrideIconTintForNavMode != null
- ? mOverrideIconTintForNavMode
- : !QuickStepContract.isGesturalMode(navigationMode);
+ return !QuickStepContract.isGesturalMode(navigationMode);
}
/**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 8a422c895052..770765260446 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -22,6 +22,8 @@ import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+import static com.android.systemui.keyguard.KeyguardViewMediator.REBOOT_MAINLINE_UPDATE;
+import static com.android.systemui.keyguard.KeyguardViewMediator.SYS_BOOT_REASON_PROP;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -72,6 +74,7 @@ import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.flags.Flags;
+import com.android.systemui.flags.SystemPropertiesHelper;
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.navigationbar.NavigationModeController;
@@ -161,6 +164,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock CentralSurfaces mCentralSurfaces;
private @Mock UiEventLogger mUiEventLogger;
private @Mock SessionTracker mSessionTracker;
+ private @Mock SystemPropertiesHelper mSystemPropertiesHelper;
private @Mock CoroutineDispatcher mDispatcher;
private @Mock DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
@@ -357,6 +361,23 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
}
@Test
+ public void testBouncerPrompt_deviceRestartedDueToMainlineUpdate() {
+ // GIVEN biometrics enrolled
+ when(mUpdateMonitor.isUnlockingWithBiometricsPossible(anyInt())).thenReturn(true);
+
+ // WHEN reboot caused by ota update
+ KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
+ mock(KeyguardUpdateMonitor.StrongAuthTracker.class);
+ when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(strongAuthTracker);
+ when(strongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(false);
+ when(mSystemPropertiesHelper.get(SYS_BOOT_REASON_PROP)).thenReturn(REBOOT_MAINLINE_UPDATE);
+
+ // THEN the bouncer prompt reason should return PROMPT_REASON_RESTART_FOR_OTA
+ assertEquals(KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE,
+ mViewMediator.mViewMediatorCallback.getBouncerPromptReason());
+ }
+
+ @Test
public void testBouncerPrompt_afterUserLockDown() {
// GIVEN biometrics enrolled
when(mUpdateMonitor.isUnlockingWithBiometricsPossible(anyInt())).thenReturn(true);
@@ -677,7 +698,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
() -> mScrimController,
mFeatureFlags,
mDispatcher,
- () -> mDreamingToLockscreenTransitionViewModel);
+ () -> mDreamingToLockscreenTransitionViewModel,
+ mSystemPropertiesHelper);
mViewMediator.start();
mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 8062272a0042..77026308ad38 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -350,7 +350,9 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
// For the Shade to animate during the Back gesture, we must enable the animation flag.
mFeatureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, true);
mFeatureFlags.set(Flags.LIGHT_REVEAL_MIGRATION, true);
+ // Turn AOD on and toggle feature flag for jank fixes
mFeatureFlags.set(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD, true);
+ when(mDozeParameters.getAlwaysOn()).thenReturn(true);
IThermalService thermalService = mock(IThermalService.class);
mPowerManager = new PowerManager(mContext, mPowerManagerService, thermalService,
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 1fa2bea6e5ea..eccff2a74eac 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -123,7 +123,14 @@ public final class CachedAppOptimizer {
"freeze_debounce_timeout";
@VisibleForTesting static final String KEY_FREEZER_EXEMPT_INST_PKG =
"freeze_exempt_inst_pkg";
-
+ @VisibleForTesting static final String KEY_FREEZER_BINDER_ENABLED =
+ "freeze_binder_enabled";
+ @VisibleForTesting static final String KEY_FREEZER_BINDER_DIVISOR =
+ "freeze_binder_divisor";
+ @VisibleForTesting static final String KEY_FREEZER_BINDER_OFFSET =
+ "freeze_binder_offset";
+ @VisibleForTesting static final String KEY_FREEZER_BINDER_THRESHOLD =
+ "freeze_binder_threshold";
static final int UNFREEZE_REASON_NONE =
FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_NONE;
@@ -237,8 +244,8 @@ public final class CachedAppOptimizer {
@VisibleForTesting static final boolean ENABLE_FILE_COMPACT = false;
// Defaults for phenotype flags.
- @VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = true;
- @VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = true;
+ @VisibleForTesting static final boolean DEFAULT_USE_COMPACTION = true;
+ @VisibleForTesting static final boolean DEFAULT_USE_FREEZER = true;
@VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_1 = 5_000;
@VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000;
@VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_3 = 500;
@@ -257,7 +264,11 @@ public final class CachedAppOptimizer {
@VisibleForTesting static final String DEFAULT_COMPACT_PROC_STATE_THROTTLE =
String.valueOf(ActivityManager.PROCESS_STATE_RECEIVER);
@VisibleForTesting static final long DEFAULT_FREEZER_DEBOUNCE_TIMEOUT = 10_000L;
- @VisibleForTesting static final Boolean DEFAULT_FREEZER_EXEMPT_INST_PKG = true;
+ @VisibleForTesting static final boolean DEFAULT_FREEZER_EXEMPT_INST_PKG = true;
+ @VisibleForTesting static final boolean DEFAULT_FREEZER_BINDER_ENABLED = true;
+ @VisibleForTesting static final long DEFAULT_FREEZER_BINDER_DIVISOR = 4;
+ @VisibleForTesting static final int DEFAULT_FREEZER_BINDER_OFFSET = 500;
+ @VisibleForTesting static final long DEFAULT_FREEZER_BINDER_THRESHOLD = 1_000;
@VisibleForTesting static final Uri CACHED_APP_FREEZER_ENABLED_URI = Settings.Global.getUriFor(
Settings.Global.CACHED_APPS_FREEZER_ENABLED);
@@ -393,6 +404,11 @@ public final class CachedAppOptimizer {
updateFreezerDebounceTimeout();
} else if (KEY_FREEZER_EXEMPT_INST_PKG.equals(name)) {
updateFreezerExemptInstPkg();
+ } else if (KEY_FREEZER_BINDER_ENABLED.equals(name)
+ || KEY_FREEZER_BINDER_DIVISOR.equals(name)
+ || KEY_FREEZER_BINDER_THRESHOLD.equals(name)
+ || KEY_FREEZER_BINDER_OFFSET.equals(name)) {
+ updateFreezerBinderState();
}
}
}
@@ -455,6 +471,16 @@ public final class CachedAppOptimizer {
@GuardedBy("mPhenotypeFlagLock")
@VisibleForTesting final Set<Integer> mProcStateThrottle;
+ @GuardedBy("mPhenotypeFlagLock")
+ @VisibleForTesting volatile boolean mFreezerBinderEnabled = DEFAULT_FREEZER_BINDER_ENABLED;
+ @GuardedBy("mPhenotypeFlagLock")
+ @VisibleForTesting volatile long mFreezerBinderDivisor = DEFAULT_FREEZER_BINDER_DIVISOR;
+ @GuardedBy("mPhenotypeFlagLock")
+ @VisibleForTesting volatile int mFreezerBinderOffset = DEFAULT_FREEZER_BINDER_OFFSET;
+ @GuardedBy("mPhenotypeFlagLock")
+ @VisibleForTesting volatile long mFreezerBinderThreshold = DEFAULT_FREEZER_BINDER_THRESHOLD;
+
+
// Handler on which compaction runs.
@VisibleForTesting
Handler mCompactionHandler;
@@ -759,6 +785,10 @@ public final class CachedAppOptimizer {
pw.println(" " + KEY_FREEZER_STATSD_SAMPLE_RATE + "=" + mFreezerStatsdSampleRate);
pw.println(" " + KEY_FREEZER_DEBOUNCE_TIMEOUT + "=" + mFreezerDebounceTimeout);
pw.println(" " + KEY_FREEZER_EXEMPT_INST_PKG + "=" + mFreezerExemptInstPkg);
+ pw.println(" " + KEY_FREEZER_BINDER_ENABLED + "=" + mFreezerBinderEnabled);
+ pw.println(" " + KEY_FREEZER_BINDER_THRESHOLD + "=" + mFreezerBinderThreshold);
+ pw.println(" " + KEY_FREEZER_BINDER_DIVISOR + "=" + mFreezerBinderDivisor);
+ pw.println(" " + KEY_FREEZER_BINDER_OFFSET + "=" + mFreezerBinderOffset);
synchronized (mProcLock) {
int size = mFrozenProcesses.size();
pw.println(" Apps frozen: " + size);
@@ -1264,6 +1294,26 @@ public final class CachedAppOptimizer {
Slog.d(TAG_AM, "Freezer exemption set to " + mFreezerExemptInstPkg);
}
+ @GuardedBy("mPhenotypeFlagLock")
+ private void updateFreezerBinderState() {
+ mFreezerBinderEnabled = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
+ KEY_FREEZER_BINDER_ENABLED, DEFAULT_FREEZER_BINDER_ENABLED);
+ mFreezerBinderDivisor = DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
+ KEY_FREEZER_BINDER_DIVISOR, DEFAULT_FREEZER_BINDER_DIVISOR);
+ mFreezerBinderOffset = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
+ KEY_FREEZER_BINDER_OFFSET, DEFAULT_FREEZER_BINDER_OFFSET);
+ mFreezerBinderThreshold = DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
+ KEY_FREEZER_BINDER_THRESHOLD, DEFAULT_FREEZER_BINDER_THRESHOLD);
+ Slog.d(TAG_AM, "Freezer binder state set to enabled=" + mFreezerBinderEnabled
+ + ", divisor=" + mFreezerBinderDivisor
+ + ", offset=" + mFreezerBinderOffset
+ + ", threshold=" + mFreezerBinderThreshold);
+ }
+
private boolean parseProcStateThrottle(String procStateThrottleString) {
String[] procStates = TextUtils.split(procStateThrottleString, ",");
mProcStateThrottle.clear();
@@ -1352,6 +1402,7 @@ public final class CachedAppOptimizer {
}
}
}
+ app.mOptRecord.setLastUsedTimeout(delayMillis);
mFreezeHandler.sendMessageDelayed(
mFreezeHandler.obtainMessage(SET_FROZEN_PROCESS_MSG, DO_FREEZE, 0, app),
delayMillis);
@@ -2121,12 +2172,54 @@ public final class CachedAppOptimizer {
}
@GuardedBy({"mAm", "mProcLock"})
- private void rescheduleFreeze(final ProcessRecord proc, final String reason,
- @UnfreezeReason int reasonCode) {
+ private void handleBinderFreezerFailure(final ProcessRecord proc, final String reason) {
+ if (!mFreezerBinderEnabled) {
+ // Just reschedule indefinitely.
+ unfreezeAppLSP(proc, UNFREEZE_REASON_BINDER_TXNS);
+ freezeAppAsyncLSP(proc);
+ return;
+ }
+ /*
+ * This handles the case where a process couldn't be frozen due to pending binder
+ * transactions. In order to prevent apps from avoiding the freezer by spamming binder
+ * transactions, there is an exponential decrease in freezer retry times plus a random
+ * offset per attempt to avoid phase issues. Once the last-attempted timeout is below a
+ * threshold, we assume that the app is spamming binder calls and can never be frozen,
+ * and we will then crash the app.
+ */
+ if (proc.mOptRecord.getLastUsedTimeout() <= mFreezerBinderThreshold) {
+ // We've given the app plenty of chances, assume broken. Time to die.
+ Slog.d(TAG_AM, "Kill app due to repeated failure to freeze binder: "
+ + proc.getPid() + " " + proc.processName);
+ mAm.mHandler.post(() -> {
+ synchronized (mAm) {
+ // Crash regardless of procstate in case the app has found another way
+ // to abuse oom_adj
+ if (proc.getThread() == null) {
+ return;
+ }
+ proc.killLocked("excessive binder traffic during cached",
+ ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
+ ApplicationExitInfo.SUBREASON_EXCESSIVE_CPU,
+ true);
+ }
+ });
+ return;
+ }
+
+ long timeout = proc.mOptRecord.getLastUsedTimeout() / mFreezerBinderDivisor;
+ // range is [-mFreezerBinderOffset, +mFreezerBinderOffset]
+ int offset = mRandom.nextInt(mFreezerBinderOffset * 2) - mFreezerBinderOffset;
+ timeout = Math.max(timeout + offset, mFreezerBinderThreshold);
+
Slog.d(TAG_AM, "Reschedule freeze for process " + proc.getPid()
- + " " + proc.processName + " (" + reason + ")");
- unfreezeAppLSP(proc, reasonCode);
- freezeAppAsyncLSP(proc);
+ + " " + proc.processName + " (" + reason + "), timeout=" + timeout);
+ Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER, ATRACE_FREEZER_TRACK,
+ "Reschedule freeze " + proc.processName + ":" + proc.getPid()
+ + " timeout=" + timeout + ", reason=" + reason);
+
+ unfreezeAppLSP(proc, UNFREEZE_REASON_BINDER_TXNS);
+ freezeAppAsyncLSP(proc, timeout);
}
/**
@@ -2173,7 +2266,7 @@ public final class CachedAppOptimizer {
// transactions that might be pending.
try {
if (freezeBinder(pid, true, FREEZE_BINDER_TIMEOUT_MS) != 0) {
- rescheduleFreeze(proc, "outstanding txns", UNFREEZE_REASON_BINDER_TXNS);
+ handleBinderFreezerFailure(proc, "outstanding txns");
return;
}
} catch (RuntimeException e) {
@@ -2234,7 +2327,7 @@ public final class CachedAppOptimizer {
if ((freezeInfo & TXNS_PENDING_WHILE_FROZEN) != 0) {
synchronized (mProcLock) {
- rescheduleFreeze(proc, "new pending txns", UNFREEZE_REASON_BINDER_TXNS);
+ handleBinderFreezerFailure(proc, "new pending txns");
}
return;
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 764bbe8bd191..f21ad2204d74 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1009,7 +1009,6 @@ public class OomAdjuster {
mCacheOomRanker.reRankLruCachedAppsLSP(mProcessList.getLruProcessesLSP(),
mProcessList.getLruProcessServiceStartLOSP());
}
- assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP());
if (computeClients) { // There won't be cycles if we didn't compute clients above.
// Cycle strategy:
@@ -1034,7 +1033,7 @@ public class OomAdjuster {
ProcessRecord app = activeProcesses.get(i);
final ProcessStateRecord state = app.mState;
if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) {
- if (computeOomAdjLSP(app, state.getCurRawAdj(), topApp, true, now,
+ if (computeOomAdjLSP(app, UNKNOWN_ADJ, topApp, true, now,
true, true)) {
retryCycles = true;
}
@@ -1044,6 +1043,8 @@ public class OomAdjuster {
}
mProcessesInCycle.clear();
+ assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP());
+
mNumNonCachedProcs = 0;
mNumCachedHiddenProcs = 0;
diff --git a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
index ffe5a6e6b958..f5c5ea8ae55a 100644
--- a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
+++ b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java
@@ -127,6 +127,12 @@ final class ProcessCachedOptimizerRecord {
@GuardedBy("mProcLock")
private @UptimeMillisLong long mEarliestFreezableTimeMillis;
+ /**
+ * This is the most recently used timeout for freezing the app in millis
+ */
+ @GuardedBy("mProcLock")
+ private long mLastUsedTimeout;
+
@GuardedBy("mProcLock")
long getLastCompactTime() {
return mLastCompactTime;
@@ -282,6 +288,16 @@ final class ProcessCachedOptimizerRecord {
}
@GuardedBy("mProcLock")
+ long getLastUsedTimeout() {
+ return mLastUsedTimeout;
+ }
+
+ @GuardedBy("mProcLock")
+ void setLastUsedTimeout(long lastUsedTimeout) {
+ mLastUsedTimeout = lastUsedTimeout;
+ }
+
+ @GuardedBy("mProcLock")
boolean isFreezeExempt() {
return mFreezeExempt;
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index ec85d577a8e7..0c7f11f98809 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -1199,11 +1199,16 @@ public class AudioDeviceInventory {
AudioDeviceInfo device = Stream.of(connectedDevices)
.filter(d -> d.getInternalType() == ada.getInternalType())
.filter(d -> (!AudioSystem.isBluetoothDevice(d.getInternalType())
- || (d.getAddress() == ada.getAddress())))
+ || (d.getAddress().equals(ada.getAddress()))))
.findFirst()
.orElse(null);
if (device == null) {
+ if (AudioService.DEBUG_DEVICES) {
+ Slog.i(TAG, "purgeRoles() removing device: " + ada.toString()
+ + ", for strategy: " + keyRole.first
+ + " and role: " + keyRole.second);
+ }
asi.deviceRoleAction(keyRole.first, keyRole.second, Arrays.asList(ada));
itDev.remove();
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index c177c4efb5ef..53ed38edffe4 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3666,25 +3666,29 @@ public class AudioService extends IAudioService.Stub
* and aliases before mute change changed and after.
*/
private void muteAliasStreams(int streamAlias, boolean state) {
- synchronized (VolumeStreamState.class) {
- List<Integer> streamsToMute = new ArrayList<>();
- for (int stream = 0; stream < mStreamStates.length; stream++) {
- VolumeStreamState vss = mStreamStates[stream];
- if (streamAlias == mStreamVolumeAlias[stream] && vss.isMutable()) {
- if (!(mCameraSoundForced
- && (vss.getStreamType()
- == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
- boolean changed = vss.mute(state, /* apply= */ false, "muteAliasStreams");
- if (changed) {
- streamsToMute.add(stream);
+ // Locking mSettingsLock to avoid inversion when calling doMute -> updateVolumeGroupIndex
+ synchronized (mSettingsLock) {
+ synchronized (VolumeStreamState.class) {
+ List<Integer> streamsToMute = new ArrayList<>();
+ for (int stream = 0; stream < mStreamStates.length; stream++) {
+ VolumeStreamState vss = mStreamStates[stream];
+ if (streamAlias == mStreamVolumeAlias[stream] && vss.isMutable()) {
+ if (!(mCameraSoundForced
+ && (vss.getStreamType()
+ == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
+ boolean changed = vss.mute(state, /* apply= */ false,
+ "muteAliasStreams");
+ if (changed) {
+ streamsToMute.add(stream);
+ }
}
}
}
+ streamsToMute.forEach(streamToMute -> {
+ mStreamStates[streamToMute].doMute();
+ broadcastMuteSetting(streamToMute, state);
+ });
}
- streamsToMute.forEach(streamToMute -> {
- mStreamStates[streamToMute].doMute();
- broadcastMuteSetting(streamToMute, state);
- });
}
}
@@ -3699,18 +3703,22 @@ public class AudioService extends IAudioService.Stub
// Called after a delay when volume down is pressed while muted
private void onUnmuteStream(int stream, int flags) {
boolean wasMuted;
- synchronized (VolumeStreamState.class) {
- final VolumeStreamState streamState = mStreamStates[stream];
- // if unmuting causes a change, it was muted
- wasMuted = streamState.mute(false, "onUnmuteStream");
+ // Locking mSettingsLock to avoid inversion when calling vss.mute -> vss.doMute ->
+ // vss.updateVolumeGroupIndex
+ synchronized (mSettingsLock) {
+ synchronized (VolumeStreamState.class) {
+ final VolumeStreamState streamState = mStreamStates[stream];
+ // if unmuting causes a change, it was muted
+ wasMuted = streamState.mute(false, "onUnmuteStream");
- final int device = getDeviceForStream(stream);
- final int index = streamState.getIndex(device);
- sendVolumeUpdate(stream, index, index, flags, device);
- }
- if (stream == AudioSystem.STREAM_MUSIC && wasMuted) {
- synchronized (mHdmiClientLock) {
- maybeSendSystemAudioStatusCommand(true);
+ final int device = getDeviceForStream(stream);
+ final int index = streamState.getIndex(device);
+ sendVolumeUpdate(stream, index, index, flags, device);
+ }
+ if (stream == AudioSystem.STREAM_MUSIC && wasMuted) {
+ synchronized (mHdmiClientLock) {
+ maybeSendSystemAudioStatusCommand(true);
+ }
}
}
}
@@ -7611,7 +7619,11 @@ public class AudioService extends IAudioService.Stub
Log.i(TAG, String.format("onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
newDevice, AudioSystem.getOutputDeviceName(newDevice)));
}
- mStreamStates[AudioSystem.STREAM_MUSIC].mute(false, "onAccessoryPlugMediaUnmute");
+ // Locking mSettingsLock to avoid inversion when calling vss.mute -> vss.doMute ->
+ // vss.updateVolumeGroupIndex
+ synchronized (mSettingsLock) {
+ mStreamStates[AudioSystem.STREAM_MUSIC].mute(false, "onAccessoryPlugMediaUnmute");
+ }
}
}
@@ -7646,9 +7658,14 @@ public class AudioService extends IAudioService.Stub
continue;
}
}
- for (int i = 0; i < sVolumeGroupStates.size(); i++) {
- final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
- vgs.applyAllVolumes(/* userSwitch= */ false);
+
+ // need mSettingsLock for vgs.applyAllVolumes -> vss.setIndex which grabs this lock after
+ // VSS.class. Locking order needs to be preserved
+ synchronized (mSettingsLock) {
+ for (int i = 0; i < sVolumeGroupStates.size(); i++) {
+ final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
+ vgs.applyAllVolumes(/* userSwitch= */ false);
+ }
}
}
@@ -7685,9 +7702,14 @@ public class AudioService extends IAudioService.Stub
if (DEBUG_VOL) {
Log.v(TAG, "restoreVolumeGroups");
}
- for (int i = 0; i < sVolumeGroupStates.size(); i++) {
- final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
- vgs.applyAllVolumes(false/*userSwitch*/);
+
+ // need mSettingsLock for vgs.applyAllVolumes -> vss.setIndex which grabs this lock after
+ // VSS.class. Locking order needs to be preserved
+ synchronized (mSettingsLock) {
+ for (int i = 0; i < sVolumeGroupStates.size(); i++) {
+ final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
+ vgs.applyAllVolumes(false/*userSwitch*/);
+ }
}
}
@@ -7824,49 +7846,51 @@ public class AudioService extends IAudioService.Stub
}
public void adjustVolume(int direction, int flags) {
- synchronized (AudioService.VolumeStreamState.class) {
- int device = getDeviceForVolume();
- int previousIndex = getIndex(device);
- if (isMuteAdjust(direction) && !isMutable()) {
- // Non mutable volume group
- if (DEBUG_VOL) {
- Log.d(TAG, "invalid mute on unmutable volume group " + name());
- }
- return;
- }
- switch (direction) {
- case AudioManager.ADJUST_TOGGLE_MUTE: {
- // Note: If muted by volume 0, unmute will restore volume 0.
- mute(!mIsMuted);
- break;
+ synchronized (mSettingsLock) {
+ synchronized (AudioService.VolumeStreamState.class) {
+ int device = getDeviceForVolume();
+ int previousIndex = getIndex(device);
+ if (isMuteAdjust(direction) && !isMutable()) {
+ // Non mutable volume group
+ if (DEBUG_VOL) {
+ Log.d(TAG, "invalid mute on unmutable volume group " + name());
+ }
+ return;
}
- case AudioManager.ADJUST_UNMUTE:
- // Note: If muted by volume 0, unmute will restore volume 0.
- mute(false);
- break;
- case AudioManager.ADJUST_MUTE:
- // May be already muted by setvolume 0, prevent from setting same value
- if (previousIndex != 0) {
- // bypass persist
- mute(true);
+ switch (direction) {
+ case AudioManager.ADJUST_TOGGLE_MUTE: {
+ // Note: If muted by volume 0, unmute will restore volume 0.
+ mute(!mIsMuted);
+ break;
}
- mIsMuted = true;
- break;
- case AudioManager.ADJUST_RAISE:
- // As for stream, RAISE during mute will increment the index
- setVolumeIndex(Math.min(previousIndex + 1, mIndexMax), device, flags);
- break;
- case AudioManager.ADJUST_LOWER:
- // For stream, ADJUST_LOWER on a muted VSS is a no-op
- // If we decide to unmute on ADJUST_LOWER, cannot fallback on
- // adjustStreamVolume for group associated to legacy stream type
- if (isMuted() && previousIndex != 0) {
+ case AudioManager.ADJUST_UNMUTE:
+ // Note: If muted by volume 0, unmute will restore volume 0.
mute(false);
- } else {
- int newIndex = Math.max(previousIndex - 1, mIndexMin);
- setVolumeIndex(newIndex, device, flags);
- }
- break;
+ break;
+ case AudioManager.ADJUST_MUTE:
+ // May be already muted by setvolume 0, prevent from setting same value
+ if (previousIndex != 0) {
+ // bypass persist
+ mute(true);
+ }
+ mIsMuted = true;
+ break;
+ case AudioManager.ADJUST_RAISE:
+ // As for stream, RAISE during mute will increment the index
+ setVolumeIndex(Math.min(previousIndex + 1, mIndexMax), device, flags);
+ break;
+ case AudioManager.ADJUST_LOWER:
+ // For stream, ADJUST_LOWER on a muted VSS is a no-op
+ // If we decide to unmute on ADJUST_LOWER, cannot fallback on
+ // adjustStreamVolume for group associated to legacy stream type
+ if (isMuted() && previousIndex != 0) {
+ mute(false);
+ } else {
+ int newIndex = Math.max(previousIndex - 1, mIndexMin);
+ setVolumeIndex(newIndex, device, flags);
+ }
+ break;
+ }
}
}
}
@@ -7878,11 +7902,13 @@ public class AudioService extends IAudioService.Stub
}
public void setVolumeIndex(int index, int flags) {
- synchronized (AudioService.VolumeStreamState.class) {
- if (mUseFixedVolume) {
- return;
+ synchronized (mSettingsLock) {
+ synchronized (AudioService.VolumeStreamState.class) {
+ if (mUseFixedVolume) {
+ return;
+ }
+ setVolumeIndex(index, getDeviceForVolume(), flags);
}
- setVolumeIndex(index, getDeviceForVolume(), flags);
}
}
@@ -8689,24 +8715,30 @@ public class AudioService extends IAudioService.Stub
// If associated to volume group, update group cache
private void updateVolumeGroupIndex(int device, boolean forceMuteState) {
- synchronized (VolumeStreamState.class) {
- if (mVolumeGroupState != null) {
- int groupIndex = (getIndex(device) + 5) / 10;
- if (DEBUG_VOL) {
- Log.d(TAG, "updateVolumeGroupIndex for stream " + mStreamType
- + ", muted=" + mIsMuted + ", device=" + device + ", index="
- + getIndex(device) + ", group " + mVolumeGroupState.name()
- + " Muted=" + mVolumeGroupState.isMuted() + ", Index=" + groupIndex
- + ", forceMuteState=" + forceMuteState);
- }
- mVolumeGroupState.updateVolumeIndex(groupIndex, device);
- // Only propage mute of stream when applicable
- if (isMutable()) {
- // For call stream, align mute only when muted, not when index is set to 0
- mVolumeGroupState.mute(
- forceMuteState ? mIsMuted :
- (groupIndex == 0 && !isCallStream(mStreamType))
- || mIsMuted);
+ // need mSettingsLock when called from setIndex for vgs.mute -> vgs.applyAllVolumes ->
+ // vss.setIndex which grabs this lock after VSS.class. Locking order needs to be
+ // preserved
+ synchronized (mSettingsLock) {
+ synchronized (VolumeStreamState.class) {
+ if (mVolumeGroupState != null) {
+ int groupIndex = (getIndex(device) + 5) / 10;
+ if (DEBUG_VOL) {
+ Log.d(TAG, "updateVolumeGroupIndex for stream " + mStreamType
+ + ", muted=" + mIsMuted + ", device=" + device + ", index="
+ + getIndex(device) + ", group " + mVolumeGroupState.name()
+ + " Muted=" + mVolumeGroupState.isMuted() + ", Index="
+ + groupIndex + ", forceMuteState=" + forceMuteState);
+ }
+ mVolumeGroupState.updateVolumeIndex(groupIndex, device);
+ // Only propage mute of stream when applicable
+ if (isMutable()) {
+ // For call stream, align mute only when muted, not when index is set to
+ // 0
+ mVolumeGroupState.mute(
+ forceMuteState ? mIsMuted :
+ (groupIndex == 0 && !isCallStream(mStreamType))
+ || mIsMuted);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index c8a17e5eea5a..3560797ce2cf 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -218,8 +218,8 @@ public class BtHelper {
if (AudioService.DEBUG_VOL) {
AudioService.sVolumeLogger.enqueue(new EventLogger.StringEvent(
"setAvrcpAbsoluteVolumeIndex: bailing due to null mA2dp").printLog(TAG));
- return;
}
+ return;
}
if (!mAvrcpAbsVolSupported) {
AudioService.sVolumeLogger.enqueue(new EventLogger.StringEvent(
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 770f04a2db5e..60e2af5f283c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -2512,6 +2512,35 @@ public class MockingOomAdjusterTests {
assertEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj());
}
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void testUpdateOomAdj_DoAll_Side_Cycle() {
+ final ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ final ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ final ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ long now = SystemClock.uptimeMillis();
+ ServiceRecord s = bindService(app, app2, null, 0, mock(IBinder.class));
+ s.startRequested = true;
+ s.lastActivity = now;
+ s = bindService(app2, app3, null, 0, mock(IBinder.class));
+ s.lastActivity = now;
+ s = bindService(app3, app2, null, 0, mock(IBinder.class));
+ s.lastActivity = now;
+
+ sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+ sService.mOomAdjuster.mNumServiceProcs = 3;
+ updateOomAdj(app, app2, app3);
+
+ assertEquals(SERVICE_ADJ, app.mState.getSetAdj());
+ assertTrue(sFirstCachedAdj <= app2.mState.getSetAdj());
+ assertTrue(sFirstCachedAdj <= app3.mState.getSetAdj());
+ assertTrue(CACHED_APP_MAX_ADJ >= app2.mState.getSetAdj());
+ assertTrue(CACHED_APP_MAX_ADJ >= app3.mState.getSetAdj());
+ }
+
private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
String packageName, boolean hasShownUi) {
long now = SystemClock.uptimeMillis();