diff options
25 files changed, 227 insertions, 74 deletions
diff --git a/Android.bp b/Android.bp index 4c44974a84d6..b1b332a9a2b5 100644 --- a/Android.bp +++ b/Android.bp @@ -389,6 +389,7 @@ java_defaults { static_libs: [ "android.hardware.common.fmq-V1-java", "bouncycastle-repackaged-unbundled", + "com.android.sysprop.foldlockbehavior", "framework-internal-utils", // If MimeMap ever becomes its own APEX, then this dependency would need to be removed // in favor of an API stubs dependency in java_library "framework" below. diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index fce5e4f1fd21..e7a5b72eafc5 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1759,12 +1759,17 @@ public class WallpaperManager { /** * Returns the information about the home screen wallpaper if its current wallpaper is a live - * wallpaper component. Otherwise, if the wallpaper is a static image or is not set, this - * returns null. + * wallpaper component. Otherwise, if the wallpaper is a static image or is not set, or if the + * the caller doesn't have the appropriate permissions, this returns {@code null}. * * <p> - * In order to use this, apps should declare a {@code <queries>} tag with the action - * {@code "android.service.wallpaper.WallpaperService"}. Otherwise, + * Before Android U, this method requires the + * {@link android.Manifest.permission#QUERY_ALL_PACKAGES} permission. + * </p> + * + * <p> + * Starting from Android U, In order to use this, apps should declare a {@code <queries>} tag + * with the action {@code "android.service.wallpaper.WallpaperService"}. Otherwise, * this method will return {@code null} if the caller doesn't otherwise have * <a href="{@docRoot}training/package-visibility">visibility</a> of the wallpaper package. * </p> @@ -1780,8 +1785,15 @@ public class WallpaperManager { /** * Returns the information about the designated wallpaper if its current wallpaper is a live - * wallpaper component. Otherwise, if the wallpaper is a static image or is not set, this - * returns null. + * wallpaper component. Otherwise, if the wallpaper is a static image or is not set, or if the + * the caller doesn't have the appropriate permissions, this returns {@code null}. + * + * <p> + * In order to use this, apps should declare a {@code <queries>} tag + * with the action {@code "android.service.wallpaper.WallpaperService"}. Otherwise, + * this method will return {@code null} if the caller doesn't otherwise have + * <a href="{@docRoot}training/package-visibility">visibility</a> of the wallpaper package. + * </p> * * @param which Specifies wallpaper to request (home or lock). * @param userId Owner of the wallpaper. diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig index b5efe588e63b..b054d38e59dc 100644 --- a/core/java/android/content/pm/flags.aconfig +++ b/core/java/android/content/pm/flags.aconfig @@ -27,3 +27,11 @@ flag { description: "Feature flag to improve stopped state enforcement" bug: "296644915" } + +flag { + name: "nullable_data_dir" + namespace: "package_manager_service" + description: "Feature flag to allow ApplicationInfo.dataDir to be null." + bug: "302587814" + is_fixed_read_only: true +} diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig index 07ff7be00114..ea0f049cece3 100644 --- a/core/java/android/content/pm/multiuser.aconfig +++ b/core/java/android/content/pm/multiuser.aconfig @@ -6,3 +6,10 @@ flag { description: "Save guest and device policy global restrictions on the SYSTEM user's XML file." bug: "301067944" } + +flag { + name: "bind_wallpaper_service_on_its_own_thread_during_a_user_switch" + namespace: "multiuser" + description: "Bind wallpaper service on its own thread instead of system_server's main handler during a user switch." + bug: "302100344" +} diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index f40232b266d0..d09f0a831f30 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -11147,12 +11147,6 @@ public final class Settings { public static final String BLUETOOTH_ON_WHILE_DRIVING = "bluetooth_on_while_driving"; /** - * Volume dialog timeout in ms. - * @hide - */ - public static final String VOLUME_DIALOG_DISMISS_TIMEOUT = "volume_dialog_dismiss_timeout"; - - /** * What behavior should be invoked when the volume hush gesture is triggered * One of VOLUME_HUSH_OFF, VOLUME_HUSH_VIBRATE, VOLUME_HUSH_MUTE. * diff --git a/core/java/com/android/internal/foldables/FoldLockSettingAvailabilityProvider.java b/core/java/com/android/internal/foldables/FoldLockSettingAvailabilityProvider.java new file mode 100644 index 000000000000..4e3888a9e92d --- /dev/null +++ b/core/java/com/android/internal/foldables/FoldLockSettingAvailabilityProvider.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2023 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.internal.foldables; + +import android.content.res.Resources; +import android.sysprop.FoldLockBehaviorProperties; + +import com.android.internal.R; + +/** + * Wrapper class to access {@link FoldLockBehaviorProperties} and also assists with testing + */ +public class FoldLockSettingAvailabilityProvider { + + boolean mFoldLockBehaviorResourceValue; + + public FoldLockSettingAvailabilityProvider(Resources resources) { + mFoldLockBehaviorResourceValue = resources.getBoolean( + R.bool.config_fold_lock_behavior); + } + + public boolean isFoldLockBehaviorAvailable() { + return mFoldLockBehaviorResourceValue + && FoldLockBehaviorProperties.fold_lock_setting_enabled().orElse(false); + } +} diff --git a/core/sysprop/Android.bp b/core/sysprop/Android.bp index f89099e5630d..512a2eb20abb 100644 --- a/core/sysprop/Android.bp +++ b/core/sysprop/Android.bp @@ -36,3 +36,10 @@ sysprop_library { api_packages: ["android.sysprop"], vendor_available: false, } + +sysprop_library { + name: "com.android.sysprop.foldlockbehavior", + srcs: ["FoldLockBehaviorProperties.sysprop"], + property_owner: "Platform", + api_packages: ["android.sysprop"], +} diff --git a/core/sysprop/FoldLockBehaviorProperties.sysprop b/core/sysprop/FoldLockBehaviorProperties.sysprop new file mode 100644 index 000000000000..d337954ff2a0 --- /dev/null +++ b/core/sysprop/FoldLockBehaviorProperties.sysprop @@ -0,0 +1,24 @@ +# Copyright (C) 2023 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. + +module: "android.sysprop.FoldLockBehaviorProperties" +owner: Platform + +prop { + api_name: "fold_lock_setting_enabled" + type: Boolean + prop_name: "persist.fold_lock_setting_enabled" + scope: Internal + access: Readonly +} diff --git a/core/sysprop/api/com.android.sysprop.foldlockbehavior-current.txt b/core/sysprop/api/com.android.sysprop.foldlockbehavior-current.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/core/sysprop/api/com.android.sysprop.foldlockbehavior-current.txt diff --git a/core/sysprop/api/com.android.sysprop.foldlockbehavior-latest.txt b/core/sysprop/api/com.android.sysprop.foldlockbehavior-latest.txt new file mode 100644 index 000000000000..13274708a20f --- /dev/null +++ b/core/sysprop/api/com.android.sysprop.foldlockbehavior-latest.txt @@ -0,0 +1,9 @@ +props { + module: "android.sysprop.FoldLockBehaviorProperties" + prop { + api_name: "fold_lock_setting_enabled" + type: Boolean + prop_name: "persist.fold_lock_setting_enabled" + scope: Internal + } +} diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index f6f75de1f24e..91d2d1bb58e5 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -143,7 +143,6 @@ public class SecureSettings { Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, Settings.Secure.SCREENSAVER_HOME_CONTROLS_ENABLED, Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, - Settings.Secure.VOLUME_DIALOG_DISMISS_TIMEOUT, Settings.Secure.VOLUME_HUSH_GESTURE, Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT, Settings.Secure.LOW_POWER_WARNING_ACKNOWLEDGED, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 8d13f01f1d03..bec144766438 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -212,7 +212,6 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.SCREENSAVER_HOME_CONTROLS_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, BOOLEAN_VALIDATOR); - VALIDATORS.put(Secure.VOLUME_DIALOG_DISMISS_TIMEOUT, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.VOLUME_HUSH_GESTURE, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put( Secure.ENABLED_NOTIFICATION_LISTENERS, diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index f7a4d47be800..a8bf229eb991 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -97,9 +97,9 @@ import com.android.keyguard.KeyguardSecurityModel.SecurityMode; import com.android.settingslib.Utils; import com.android.settingslib.drawable.CircleFramedDrawable; import com.android.systemui.Gefingerpoken; -import com.android.systemui.res.R; import com.android.systemui.classifier.FalsingA11yDelegate; import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.res.R; import com.android.systemui.shade.TouchLogger; import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.policy.BaseUserSwitcherAdapter; @@ -1191,6 +1191,7 @@ public class KeyguardSecurityContainer extends ConstraintLayout { mPopup.setOnItemClickListener((parent, view, pos, id) -> { if (mFalsingManager.isFalseTap(LOW_PENALTY)) return; if (!view.isEnabled()) return; + if (mPopup == null) return; // Subtract one for the header UserRecord user = adapter.getItem(pos - 1); if (user.isManageUsers || user.isAddSupervisedUser) { diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index a00c3b5ae38e..dd6093d25b75 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -115,7 +115,7 @@ object Flags { // TODO(b/292213543): Tracking Bug @JvmField val NOTIFICATION_GROUP_EXPANSION_CHANGE = - unreleasedFlag("notification_group_expansion_change") + unreleasedFlag("notification_group_expansion_change", teamfood = true) // TODO(b/301955929) @JvmField diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index 70df09d0876b..69fe46aa9009 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -83,7 +83,7 @@ import java.util.ArrayList; */ public abstract class QSTileImpl<TState extends State> implements QSTile, LifecycleOwner, Dumpable { protected final String TAG = "Tile." + getClass().getSimpleName(); - protected static final boolean DEBUG = Log.isLoggable("Tile", Log.DEBUG); + protected final boolean DEBUG = Log.isLoggable("Tile", Log.DEBUG); private static final long DEFAULT_STALE_TIMEOUT = 10 * DateUtils.MINUTE_IN_MILLIS; protected static final Object ARG_SHOW_TRANSIENT_ENABLING = new Object(); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 3c6d90dc08d2..727d649c8118 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -135,7 +135,6 @@ import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.util.AlphaTintDrawableWrapper; import com.android.systemui.util.RoundedCornerProgressDrawable; -import com.android.systemui.util.settings.SecureSettings; import java.io.PrintWriter; import java.util.ArrayList; @@ -305,8 +304,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, private @DevicePostureController.DevicePostureInt int mDevicePosture; private int mOrientation; private final FeatureFlags mFeatureFlags; - private final SecureSettings mSecureSettings; - private int mDialogTimeoutMillis; public VolumeDialogImpl( Context context, @@ -323,8 +320,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, DevicePostureController devicePostureController, Looper looper, DumpManager dumpManager, - FeatureFlags featureFlags, - SecureSettings secureSettings) { + FeatureFlags featureFlags) { mFeatureFlags = featureFlags; mContext = new ContextThemeWrapper(context, R.style.volume_dialog_theme); @@ -355,8 +351,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, mUseBackgroundBlur = mContext.getResources().getBoolean(R.bool.config_volumeDialogUseBackgroundBlur); mInteractionJankMonitor = interactionJankMonitor; - mSecureSettings = secureSettings; - mDialogTimeoutMillis = DIALOG_TIMEOUT_MILLIS; dumpManager.registerDumpable("VolumeDialogImpl", this); @@ -521,8 +515,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, mDialog.setContentView(R.layout.volume_dialog); mDialogView = mDialog.findViewById(R.id.volume_dialog); mDialogView.setAlpha(0); - mDialogTimeoutMillis = mSecureSettings.getInt(Settings.Secure.VOLUME_DIALOG_DISMISS_TIMEOUT, - DIALOG_TIMEOUT_MILLIS); mDialog.setCanceledOnTouchOutside(true); mDialog.setOnShowListener(dialog -> { mDialogView.getViewTreeObserver().addOnComputeInternalInsetsListener(this); @@ -535,7 +527,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, .alpha(1) .translationX(0) .setDuration(mDialogShowAnimationDurationMs) - .setListener(getJankListener(getDialogView(), TYPE_SHOW, mDialogTimeoutMillis)) + .setListener(getJankListener(getDialogView(), TYPE_SHOW, DIALOG_TIMEOUT_MILLIS)) .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator()) .withEndAction(() -> { if (!Prefs.getBoolean(mContext, Prefs.Key.TOUCHED_RINGER_TOGGLE, false)) { @@ -1522,7 +1514,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable, AccessibilityManager.FLAG_CONTENT_TEXT | AccessibilityManager.FLAG_CONTENT_CONTROLS); } - return mAccessibilityMgr.getRecommendedTimeoutMillis(mDialogTimeoutMillis, + return mAccessibilityMgr.getRecommendedTimeoutMillis(DIALOG_TIMEOUT_MILLIS, AccessibilityManager.FLAG_CONTENT_CONTROLS); } diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java index 624691b19704..cc9f3e14216e 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java +++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java @@ -31,7 +31,6 @@ import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; -import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.volume.CsdWarningDialog; import com.android.systemui.volume.VolumeComponent; import com.android.systemui.volume.VolumeDialogComponent; @@ -64,8 +63,7 @@ public interface VolumeModule { CsdWarningDialog.Factory csdFactory, DevicePostureController devicePostureController, DumpManager dumpManager, - FeatureFlags featureFlags, - SecureSettings secureSettings) { + FeatureFlags featureFlags) { VolumeDialogImpl impl = new VolumeDialogImpl( context, volumeDialogController, @@ -81,8 +79,7 @@ public interface VolumeModule { devicePostureController, Looper.getMainLooper(), dumpManager, - featureFlags, - secureSettings); + featureFlags); impl.setStreamImportant(AudioManager.STREAM_SYSTEM, false); impl.setAutomute(true); impl.setSilentMode(false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java index daf88773780e..28fc5db150b7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java @@ -42,7 +42,6 @@ import android.app.KeyguardManager; import android.content.res.Configuration; import android.media.AudioManager; import android.os.SystemClock; -import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.Log; @@ -71,7 +70,6 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.FakeConfigurationController; -import com.android.systemui.util.settings.FakeSettings; import org.junit.After; import org.junit.Before; @@ -136,8 +134,6 @@ public class VolumeDialogImplTest extends SysuiTestCase { private FakeFeatureFlags mFeatureFlags; private int mLongestHideShowAnimationDuration = 250; - private FakeSettings mSecureSettings; - @Rule public final AnimatorTestRule mAnimatorTestRule = new AnimatorTestRule(); @@ -166,8 +162,6 @@ public class VolumeDialogImplTest extends SysuiTestCase { mFeatureFlags = new FakeFeatureFlags(); - mSecureSettings = new FakeSettings(); - mDialog = new VolumeDialogImpl( getContext(), mVolumeDialogController, @@ -183,8 +177,7 @@ public class VolumeDialogImplTest extends SysuiTestCase { mPostureController, mTestableLooper.getLooper(), mDumpManager, - mFeatureFlags, - mSecureSettings); + mFeatureFlags); mDialog.init(0, null); State state = createShellState(); mDialog.onStateChangedH(state); @@ -249,18 +242,6 @@ public class VolumeDialogImplTest extends SysuiTestCase { } @Test - public void testSetTimeoutValue_ComputeTimeout() { - mSecureSettings.putInt(Settings.Secure.VOLUME_DIALOG_DISMISS_TIMEOUT, 7000); - Mockito.reset(mAccessibilityMgr); - mDialog.init(0, null); - mDialog.rescheduleTimeoutH(); - verify(mAccessibilityMgr).getRecommendedTimeoutMillis( - 7000, - AccessibilityManager.FLAG_CONTENT_CONTROLS); - } - - - @Test public void testComputeTimeout_tooltip() { Mockito.reset(mAccessibilityMgr); mDialog.showCaptionsTooltip(); diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index e17424bac6b3..6e984bb4bb7b 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -250,6 +250,7 @@ public class Watchdog implements Dumpable { private Monitor mCurrentMonitor; private long mStartTimeMillis; private int mPauseCount; + private long mOneOffTimeoutMillis; HandlerChecker(Handler handler, String name) { mHandler = handler; @@ -269,7 +270,13 @@ public class Watchdog implements Dumpable { * @param handlerCheckerTimeoutMillis the timeout to use for this run */ public void scheduleCheckLocked(long handlerCheckerTimeoutMillis) { - mWaitMaxMillis = handlerCheckerTimeoutMillis; + if (mOneOffTimeoutMillis > 0) { + mWaitMaxMillis = mOneOffTimeoutMillis; + mOneOffTimeoutMillis = 0; + } else { + mWaitMaxMillis = handlerCheckerTimeoutMillis; + } + if (mCompleted) { // Safe to update monitors in queue, Handler is not in the middle of work mMonitors.addAll(mMonitorQueue); @@ -352,6 +359,23 @@ public class Watchdog implements Dumpable { } } + /** + * Sets the timeout of the HandlerChecker for one run. + * + * <p>The current run will be ignored and the next run will be set to this timeout. + * + * <p>If a one off timeout is already set, the maximum timeout will be used. + */ + public void setOneOffTimeoutLocked(int temporaryTimeoutMillis, String reason) { + mOneOffTimeoutMillis = Math.max(temporaryTimeoutMillis, mOneOffTimeoutMillis); + // Mark as completed, because there's a chance we called this after the watchog + // thread loop called Object#wait after 'WAITED_HALF'. In that case we want to ensure + // the next call to #getCompletionStateLocked for this checker returns 'COMPLETED' + mCompleted = true; + Slog.i(TAG, "Extending timeout of HandlerChecker: " + mName + " for reason: " + + reason + ". New timeout: " + mOneOffTimeoutMillis); + } + /** Pause the HandlerChecker. */ public void pauseLocked(String reason) { mPauseCount++; @@ -598,6 +622,27 @@ public class Watchdog implements Dumpable { } } + /** + * Sets a one-off timeout for the next run of the watchdog for this thread. This is useful + * to run a slow operation on one of the monitored thread. + * + * <p>After the next run, the timeout will go back to the default value. + * + * <p>If the current thread has not been added to the Watchdog, this call is a no-op. + * + * <p>If a one-off timeout for the current thread is already, the max value will be used. + */ + public void setOneOffTimeoutForCurrentThread(int oneOffTimeoutMillis, String reason) { + synchronized (mLock) { + for (HandlerCheckerAndTimeout hc : mHandlerCheckers) { + HandlerChecker checker = hc.checker(); + if (Thread.currentThread().equals(checker.getThread())) { + checker.setOneOffTimeoutLocked(oneOffTimeoutMillis, reason); + } + } + } + } + /** * Pauses Watchdog action for the currently running thread. Useful before executing long running * operations that could falsely trigger the watchdog. Each call to this will require a matching @@ -609,7 +654,7 @@ public class Watchdog implements Dumpable { * adds another pause and will require an additional {@link #resumeCurrentThread} to resume. * * <p>Note: Use with care, as any deadlocks on the current thread will be undetected until all - * pauses have been resumed. + * pauses have been resumed. Prefer to use #setOneOffTimeoutForCurrentThread. */ public void pauseWatchingCurrentThread(String reason) { synchronized (mLock) { diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index e942c1711088..d372f3031b81 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -142,6 +142,7 @@ import android.window.ScreenCapture; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.display.BrightnessSynchronizer; +import com.android.internal.foldables.FoldLockSettingAvailabilityProvider; import com.android.internal.os.BackgroundThread; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; @@ -548,6 +549,9 @@ public final class DisplayManagerService extends SystemService { @VisibleForTesting DisplayManagerService(Context context, Injector injector) { super(context); + FoldSettingProvider foldSettingProvider = new FoldSettingProvider(context, + new SettingsWrapper(), + new FoldLockSettingAvailabilityProvider(context.getResources())); mInjector = injector; mContext = context; mFlags = injector.getFlags(); @@ -555,8 +559,8 @@ public final class DisplayManagerService extends SystemService { mUiHandler = UiThread.getHandler(); mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore); mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, - new FoldSettingProvider(mContext, new SettingsWrapper()), mDisplayDeviceRepo, - new LogicalDisplayListener(), mSyncRoot, mHandler, mFlags); + foldSettingProvider, + mDisplayDeviceRepo, new LogicalDisplayListener(), mSyncRoot, mHandler, mFlags); mDisplayModeDirector = new DisplayModeDirector(context, mHandler, mFlags); mBrightnessSynchronizer = new BrightnessSynchronizer(mContext); Resources resources = mContext.getResources(); diff --git a/services/core/java/com/android/server/utils/FoldSettingProvider.java b/services/core/java/com/android/server/utils/FoldSettingProvider.java index d62628b73019..552343ab56a3 100644 --- a/services/core/java/com/android/server/utils/FoldSettingProvider.java +++ b/services/core/java/com/android/server/utils/FoldSettingProvider.java @@ -22,7 +22,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.util.Log; -import com.android.internal.R; +import com.android.internal.foldables.FoldLockSettingAvailabilityProvider; import com.android.internal.util.SettingsWrapper; import java.util.Set; @@ -51,14 +51,14 @@ public class FoldSettingProvider { private static final String TAG = "FoldSettingProvider"; private final ContentResolver mContentResolver; - private final boolean mIsFoldLockBehaviorAvailable; private final SettingsWrapper mSettingsWrapper; + private final FoldLockSettingAvailabilityProvider mFoldLockSettingAvailabilityProvider; - public FoldSettingProvider(Context context, SettingsWrapper settingsWrapper) { + public FoldSettingProvider(Context context, SettingsWrapper settingsWrapper, + FoldLockSettingAvailabilityProvider foldLockSettingAvailabilityProvider) { mContentResolver = context.getContentResolver(); mSettingsWrapper = settingsWrapper; - mIsFoldLockBehaviorAvailable = context.getResources().getBoolean( - R.bool.config_fold_lock_behavior); + mFoldLockSettingAvailabilityProvider = foldLockSettingAvailabilityProvider; } /** @@ -83,7 +83,9 @@ public class FoldSettingProvider { } private String getFoldSettingValue() { - if (!mIsFoldLockBehaviorAvailable) { + boolean isFoldLockBehaviorAvailable = + mFoldLockSettingAvailabilityProvider.isFoldLockBehaviorAvailable(); + if (!isFoldLockBehaviorAvailable) { return SETTING_VALUE_DEFAULT; } String foldSettingValue = mSettingsWrapper.getStringForUser( diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 4c525e902b88..01ea33f1aecd 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -28,6 +28,7 @@ import static android.os.ParcelFileDescriptor.MODE_CREATE; import static android.os.ParcelFileDescriptor.MODE_READ_ONLY; import static android.os.ParcelFileDescriptor.MODE_READ_WRITE; import static android.os.ParcelFileDescriptor.MODE_TRUNCATE; +import static android.os.Process.THREAD_PRIORITY_FOREGROUND; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; @@ -74,6 +75,7 @@ import android.graphics.BitmapFactory; import android.graphics.Rect; import android.graphics.RectF; import android.hardware.display.DisplayManager; +import android.multiuser.Flags; import android.os.Binder; import android.os.Bundle; import android.os.FileObserver; @@ -114,6 +116,7 @@ import com.android.internal.util.DumpUtils; import com.android.server.EventLogTags; import com.android.server.FgThread; import com.android.server.LocalServices; +import com.android.server.ServiceThread; import com.android.server.SystemService; import com.android.server.pm.UserManagerInternal; import com.android.server.utils.TimingsTraceAndSlog; @@ -132,6 +135,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import java.util.function.Predicate; @@ -746,6 +750,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } private final Context mContext; + private final AtomicBoolean mIsInitialBinding = new AtomicBoolean(true); + private final ServiceThread mHandlerThread; private final WindowManagerInternal mWindowManagerInternal; private final PackageManagerInternal mPackageManagerInternal; private final IPackageManager mIPackageManager; @@ -1619,6 +1625,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub public WallpaperManagerService(Context context) { if (DEBUG) Slog.v(TAG, "WallpaperService startup"); mContext = context; + if (Flags.bindWallpaperServiceOnItsOwnThreadDuringAUserSwitch()) { + mHandlerThread = new ServiceThread(TAG, THREAD_PRIORITY_FOREGROUND, true /*allowIo*/); + mHandlerThread.start(); + } else { + mHandlerThread = null; + } mShuttingDown = false; mImageWallpaper = ComponentName.unflattenFromString( context.getResources().getString(R.string.image_wallpaper_component)); @@ -3652,7 +3664,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub com.android.internal.R.bool.config_wallpaperTopApp)) { bindFlags |= Context.BIND_SCHEDULE_LIKE_TOP_APP; } - boolean bindSuccess = mContext.bindServiceAsUser(intent, newConn, bindFlags, + Handler handler = Flags.bindWallpaperServiceOnItsOwnThreadDuringAUserSwitch() + && !mIsInitialBinding.compareAndSet(true, false) + ? mHandlerThread.getThreadHandler() : mContext.getMainThreadHandler(); + boolean bindSuccess = mContext.bindServiceAsUser(intent, newConn, bindFlags, handler, new UserHandle(serviceUserId)); if (!bindSuccess) { String msg = "Unable to bind service: " + componentName; diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java index dca69eb6dd98..8b54d6d22c2b 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerController2Test.java @@ -38,6 +38,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; +import android.app.ActivityManager; import android.content.Context; import android.content.res.Resources; import android.hardware.Sensor; @@ -158,6 +159,7 @@ public final class DisplayPowerController2Test { .setStrictness(Strictness.LENIENT) .spyStatic(SystemProperties.class) .spyStatic(BatteryStatsService.class) + .spyStatic(ActivityManager.class) .build(); @Rule @@ -182,9 +184,14 @@ public final class DisplayPowerController2Test { mContext.addMockSystemService(PowerManager.class, mPowerManagerMock); + mContext.getOrCreateTestableResources().addOverride( + com.android.internal.R.bool.config_displayColorFadeDisabled, false); + doAnswer((Answer<Void>) invocationOnMock -> null).when(() -> SystemProperties.set(anyString(), any())); doAnswer((Answer<Void>) invocationOnMock -> null).when(BatteryStatsService::getService); + doAnswer((Answer<Boolean>) invocationOnMock -> false) + .when(ActivityManager::isLowRamDeviceStatic); setUpSensors(); mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID); diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java index edaa1d5013bf..37ee23f38b14 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java @@ -38,6 +38,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; +import android.app.ActivityManager; import android.content.Context; import android.content.res.Resources; import android.hardware.Sensor; @@ -158,6 +159,7 @@ public final class DisplayPowerControllerTest { .setStrictness(Strictness.LENIENT) .spyStatic(SystemProperties.class) .spyStatic(BatteryStatsService.class) + .spyStatic(ActivityManager.class) .build(); @Rule @@ -186,9 +188,14 @@ public final class DisplayPowerControllerTest { mContext.addMockSystemService(PowerManager.class, mPowerManagerMock); + mContext.getOrCreateTestableResources().addOverride( + com.android.internal.R.bool.config_displayColorFadeDisabled, false); + doAnswer((Answer<Void>) invocationOnMock -> null).when(() -> SystemProperties.set(anyString(), any())); doAnswer((Answer<Void>) invocationOnMock -> null).when(BatteryStatsService::getService); + doAnswer((Answer<Boolean>) invocationOnMock -> false) + .when(ActivityManager::isLowRamDeviceStatic); setUpSensors(); mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID); diff --git a/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java b/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java index 3514276ccb5b..4c4e9dfe0b98 100644 --- a/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/utils/FoldSettingProviderTest.java @@ -27,13 +27,12 @@ import static org.mockito.Mockito.when; import android.content.ContentResolver; import android.content.Context; -import android.content.res.Resources; import android.os.UserHandle; import android.provider.Settings; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.internal.R; +import com.android.internal.foldables.FoldLockSettingAvailabilityProvider; import com.android.internal.util.SettingsWrapper; import org.junit.Before; @@ -48,9 +47,9 @@ public class FoldSettingProviderTest { @Mock private Context mContext; @Mock - private Resources mResources; - @Mock private SettingsWrapper mSettingsWrapper; + @Mock + private FoldLockSettingAvailabilityProvider mFoldLockSettingAvailabilityProvider; private ContentResolver mContentResolver; private FoldSettingProvider mFoldSettingProvider; @@ -61,17 +60,18 @@ public class FoldSettingProviderTest { mContentResolver = InstrumentationRegistry.getInstrumentation().getContext().getContentResolver(); when(mContext.getContentResolver()).thenReturn(mContentResolver); - when(mContext.getResources()).thenReturn(mResources); setFoldLockBehaviorAvailability(true); - mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper); + mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper, + mFoldLockSettingAvailabilityProvider); } @Test public void foldSettingNotAvailable_returnDefaultSetting() { setFoldLockBehaviorAvailability(false); setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD); - mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper); + mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper, + mFoldLockSettingAvailabilityProvider); boolean shouldSelectiveStayAwakeOnFold = mFoldSettingProvider.shouldSelectiveStayAwakeOnFold(); @@ -83,7 +83,8 @@ public class FoldSettingProviderTest { public void foldSettingNotAvailable_notReturnStayAwakeOnFoldTrue() { setFoldLockBehaviorAvailability(false); setFoldLockBehaviorSettingValue(SETTING_VALUE_STAY_AWAKE_ON_FOLD); - mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper); + mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper, + mFoldLockSettingAvailabilityProvider); boolean shouldStayAwakeOnFold = mFoldSettingProvider.shouldStayAwakeOnFold(); @@ -94,7 +95,8 @@ public class FoldSettingProviderTest { public void foldSettingNotAvailable_notReturnSleepOnFoldTrue() { setFoldLockBehaviorAvailability(false); setFoldLockBehaviorSettingValue(SETTING_VALUE_SLEEP_ON_FOLD); - mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper); + mFoldSettingProvider = new FoldSettingProvider(mContext, mSettingsWrapper, + mFoldLockSettingAvailabilityProvider); boolean shouldSleepOnFold = mFoldSettingProvider.shouldSleepOnFold(); @@ -131,7 +133,7 @@ public class FoldSettingProviderTest { } private void setFoldLockBehaviorAvailability(boolean isFoldLockBehaviorEnabled) { - when(mResources.getBoolean(R.bool.config_fold_lock_behavior)).thenReturn( + when(mFoldLockSettingAvailabilityProvider.isFoldLockBehaviorAvailable()).thenReturn( isFoldLockBehaviorEnabled); } |