diff options
15 files changed, 349 insertions, 61 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java index 20bca3530b63..52dc01b8df30 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java @@ -460,14 +460,14 @@ class JobConcurrencyManager { if (mPowerManager != null && mPowerManager.isDeviceIdleMode()) { synchronized (mLock) { stopUnexemptedJobsForDoze(); - stopLongRunningJobsLocked("deep doze"); + stopOvertimeJobsLocked("deep doze"); } } break; case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED: if (mPowerManager != null && mPowerManager.isPowerSaveMode()) { synchronized (mLock) { - stopLongRunningJobsLocked("battery saver"); + stopOvertimeJobsLocked("battery saver"); } } break; @@ -555,7 +555,7 @@ class JobConcurrencyManager { * execution guarantee. */ @GuardedBy("mLock") - boolean isJobLongRunningLocked(@NonNull JobStatus job) { + boolean isJobInOvertimeLocked(@NonNull JobStatus job) { if (!mRunningJobs.contains(job)) { return false; } @@ -1043,7 +1043,7 @@ class JobConcurrencyManager { } @GuardedBy("mLock") - private void stopLongRunningJobsLocked(@NonNull String debugReason) { + private void stopOvertimeJobsLocked(@NonNull String debugReason) { for (int i = 0; i < mActiveServices.size(); ++i) { final JobServiceContext jsc = mActiveServices.get(i); final JobStatus jobStatus = jsc.getRunningJobLocked(); @@ -1060,7 +1060,7 @@ class JobConcurrencyManager { * restricted by the given {@link JobRestriction}. */ @GuardedBy("mLock") - void maybeStopLongRunningJobsLocked(@NonNull JobRestriction restriction) { + void maybeStopOvertimeJobsLocked(@NonNull JobRestriction restriction) { for (int i = mActiveServices.size() - 1; i >= 0; --i) { final JobServiceContext jsc = mActiveServices.get(i); final JobStatus jobStatus = jsc.getRunningJobLocked(); diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java index d28ebde9cb23..6375d0deae40 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -1870,10 +1870,10 @@ public class JobSchedulerService extends com.android.server.SystemService return mConcurrencyManager.isJobRunningLocked(job); } - /** @see JobConcurrencyManager#isJobLongRunningLocked(JobStatus) */ + /** @see JobConcurrencyManager#isJobInOvertimeLocked(JobStatus) */ @GuardedBy("mLock") - public boolean isLongRunningLocked(JobStatus job) { - return mConcurrencyManager.isJobLongRunningLocked(job); + public boolean isJobInOvertimeLocked(JobStatus job) { + return mConcurrencyManager.isJobInOvertimeLocked(job); } private void noteJobPending(JobStatus job) { @@ -2155,11 +2155,11 @@ public class JobSchedulerService extends com.android.server.SystemService @Override public void onRestrictionStateChanged(@NonNull JobRestriction restriction, - boolean stopLongRunningJobs) { + boolean stopOvertimeJobs) { mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget(); - if (stopLongRunningJobs) { + if (stopOvertimeJobs) { synchronized (mLock) { - mConcurrencyManager.maybeStopLongRunningJobsLocked(restriction); + mConcurrencyManager.maybeStopOvertimeJobsLocked(restriction); } } } diff --git a/apex/jobscheduler/service/java/com/android/server/job/StateChangedListener.java b/apex/jobscheduler/service/java/com/android/server/job/StateChangedListener.java index d7bd03025fde..554f152dccfb 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/StateChangedListener.java +++ b/apex/jobscheduler/service/java/com/android/server/job/StateChangedListener.java @@ -41,11 +41,11 @@ public interface StateChangedListener { * Called by a {@link com.android.server.job.restrictions.JobRestriction} to notify the * JobScheduler that it should check on the state of all jobs. * - * @param stopLongRunningJobs Whether to stop any jobs that have run for more than their minimum - * execution guarantee and are restricted by the changed restriction + * @param stopOvertimeJobs Whether to stop any jobs that have run for more than their minimum + * execution guarantee and are restricted by the changed restriction */ void onRestrictionStateChanged(@NonNull JobRestriction restriction, - boolean stopLongRunningJobs); + boolean stopOvertimeJobs); /** * Called by the controller to notify the JobManager that regardless of the state of the task, diff --git a/apex/jobscheduler/service/java/com/android/server/job/restrictions/ThermalStatusRestriction.java b/apex/jobscheduler/service/java/com/android/server/job/restrictions/ThermalStatusRestriction.java index a007a69a29e3..ca2fd60a07b2 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/restrictions/ThermalStatusRestriction.java +++ b/apex/jobscheduler/service/java/com/android/server/job/restrictions/ThermalStatusRestriction.java @@ -90,11 +90,11 @@ public class ThermalStatusRestriction extends JobRestriction { final int priority = job.getEffectivePriority(); if (mThermalStatus >= HIGHER_PRIORITY_THRESHOLD) { // For moderate throttling, only let expedited jobs and high priority regular jobs that - // haven't been running for long run. + // haven't been running for a long time run. return !job.shouldTreatAsExpeditedJob() && !(priority == JobInfo.PRIORITY_HIGH && mService.isCurrentlyRunningLocked(job) - && !mService.isLongRunningLocked(job)); + && !mService.isJobInOvertimeLocked(job)); } if (mThermalStatus >= LOW_PRIORITY_THRESHOLD) { // For light throttling, throttle all min priority jobs and all low priority jobs that @@ -102,7 +102,7 @@ public class ThermalStatusRestriction extends JobRestriction { return priority == JobInfo.PRIORITY_MIN || (priority == JobInfo.PRIORITY_LOW && (!mService.isCurrentlyRunningLocked(job) - || mService.isLongRunningLocked(job))); + || mService.isJobInOvertimeLocked(job))); } return false; } diff --git a/core/java/android/service/dreams/DreamManagerInternal.java b/core/java/android/service/dreams/DreamManagerInternal.java index 295171ca9bbd..5f30ad054c50 100644 --- a/core/java/android/service/dreams/DreamManagerInternal.java +++ b/core/java/android/service/dreams/DreamManagerInternal.java @@ -54,6 +54,13 @@ public abstract class DreamManagerInternal { public abstract void requestDream(); /** + * Whether dreaming can start given user settings and the current dock/charge state. + * + * @param isScreenOn True if the screen is currently on. + */ + public abstract boolean canStartDreaming(boolean isScreenOn); + + /** * Called by the ActivityTaskManagerService to verify that the startDreamActivity * request comes from the current active dream component. * diff --git a/core/java/com/android/internal/inputmethod/IInputMethodManagerGlobal.java b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java index 5392bdcec5ee..e32c6aafc4df 100644 --- a/core/java/com/android/internal/inputmethod/IInputMethodManagerGlobal.java +++ b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.internal.inputmethod; +package android.view.inputmethod; import android.annotation.AnyThread; import android.annotation.NonNull; @@ -36,8 +36,11 @@ import java.util.function.Consumer; * * <p>All public methods are guaranteed to do nothing when {@link IInputMethodManager} is * unavailable.</p> + * + * <p>If you want to use any of this method outside of {@code android.view.inputmethod}, create + * a wrapper method in {@link InputMethodManagerGlobal} instead of making this class public.</p> */ -public final class IInputMethodManagerGlobal { +final class IInputMethodManagerGlobalInvoker { @Nullable private static volatile IInputMethodManager sServiceCache = null; @@ -45,7 +48,7 @@ public final class IInputMethodManagerGlobal { * @return {@code true} if {@link IInputMethodManager} is available. */ @AnyThread - public static boolean isAvailable() { + static boolean isAvailable() { return getService() != null; } @@ -79,14 +82,14 @@ public final class IInputMethodManagerGlobal { * * @param protoDump client or service side information to be stored by the server * @param source where the information is coming from, refer to - * {@link ImeTracing#IME_TRACING_FROM_CLIENT} and - * {@link ImeTracing#IME_TRACING_FROM_IMS} + * {@link com.android.internal.inputmethod.ImeTracing#IME_TRACING_FROM_CLIENT} and + * {@link com.android.internal.inputmethod.ImeTracing#IME_TRACING_FROM_IMS} * @param where where the information is coming from. * @param exceptionHandler an optional {@link RemoteException} handler. */ @RequiresNoPermission @AnyThread - public static void startProtoDump(byte[] protoDump, int source, String where, + static void startProtoDump(byte[] protoDump, int source, String where, @Nullable Consumer<RemoteException> exceptionHandler) { final IInputMethodManager service = getService(); if (service == null) { @@ -106,7 +109,7 @@ public final class IInputMethodManagerGlobal { */ @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) @AnyThread - public static void startImeTrace(@Nullable Consumer<RemoteException> exceptionHandler) { + static void startImeTrace(@Nullable Consumer<RemoteException> exceptionHandler) { final IInputMethodManager service = getService(); if (service == null) { return; @@ -125,7 +128,7 @@ public final class IInputMethodManagerGlobal { */ @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) @AnyThread - public static void stopImeTrace(@Nullable Consumer<RemoteException> exceptionHandler) { + static void stopImeTrace(@Nullable Consumer<RemoteException> exceptionHandler) { final IInputMethodManager service = getService(); if (service == null) { return; @@ -144,7 +147,7 @@ public final class IInputMethodManagerGlobal { */ @RequiresNoPermission @AnyThread - public static boolean isImeTraceEnabled() { + static boolean isImeTraceEnabled() { final IInputMethodManager service = getService(); if (service == null) { return false; @@ -161,7 +164,7 @@ public final class IInputMethodManagerGlobal { */ @RequiresPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW) @AnyThread - public static void removeImeSurface(@Nullable Consumer<RemoteException> exceptionHandler) { + static void removeImeSurface(@Nullable Consumer<RemoteException> exceptionHandler) { final IInputMethodManager service = getService(); if (service == null) { return; diff --git a/core/java/android/view/inputmethod/InputMethodManagerGlobal.java b/core/java/android/view/inputmethod/InputMethodManagerGlobal.java new file mode 100644 index 000000000000..63d9167bb2f9 --- /dev/null +++ b/core/java/android/view/inputmethod/InputMethodManagerGlobal.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.inputmethod; + +import android.annotation.AnyThread; +import android.annotation.Nullable; +import android.annotation.RequiresNoPermission; +import android.annotation.RequiresPermission; +import android.os.RemoteException; + +import com.android.internal.inputmethod.ImeTracing; +import com.android.internal.view.IInputMethodManager; + +import java.util.function.Consumer; + +/** + * Defines a set of static methods that can be used globally by framework classes. + * + * @hide + */ +public class InputMethodManagerGlobal { + /** + * @return {@code true} if IME tracing is currently is available. + */ + @AnyThread + public static boolean isImeTraceAvailable() { + return IInputMethodManagerGlobalInvoker.isAvailable(); + } + + /** + * Invokes {@link IInputMethodManager#startProtoDump(byte[], int, String)}. + * + * @param protoDump client or service side information to be stored by the server + * @param source where the information is coming from, refer to + * {@link ImeTracing#IME_TRACING_FROM_CLIENT} and + * {@link ImeTracing#IME_TRACING_FROM_IMS} + * @param where where the information is coming from. + * @param exceptionHandler an optional {@link RemoteException} handler. + */ + @RequiresNoPermission + @AnyThread + public static void startProtoDump(byte[] protoDump, int source, String where, + @Nullable Consumer<RemoteException> exceptionHandler) { + IInputMethodManagerGlobalInvoker.startProtoDump(protoDump, source, where, exceptionHandler); + } + + /** + * Invokes {@link IInputMethodManager#startImeTrace()}. + * + * @param exceptionHandler an optional {@link RemoteException} handler. + */ + @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) + @AnyThread + public static void startImeTrace(@Nullable Consumer<RemoteException> exceptionHandler) { + IInputMethodManagerGlobalInvoker.startImeTrace(exceptionHandler); + } + + /** + * Invokes {@link IInputMethodManager#stopImeTrace()}. + * + * @param exceptionHandler an optional {@link RemoteException} handler. + */ + @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) + @AnyThread + public static void stopImeTrace(@Nullable Consumer<RemoteException> exceptionHandler) { + IInputMethodManagerGlobalInvoker.stopImeTrace(exceptionHandler); + } + + /** + * Invokes {@link IInputMethodManager#isImeTraceEnabled()}. + * + * @return The return value of {@link IInputMethodManager#isImeTraceEnabled()}. + */ + @RequiresNoPermission + @AnyThread + public static boolean isImeTraceEnabled() { + return IInputMethodManagerGlobalInvoker.isImeTraceEnabled(); + } + + /** + * Invokes {@link IInputMethodManager#removeImeSurface()} + * + * @param exceptionHandler an optional {@link RemoteException} handler. + */ + @RequiresPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW) + @AnyThread + public static void removeImeSurface(@Nullable Consumer<RemoteException> exceptionHandler) { + IInputMethodManagerGlobalInvoker.removeImeSurface(exceptionHandler); + } +} diff --git a/core/java/com/android/internal/inputmethod/ImeTracing.java b/core/java/com/android/internal/inputmethod/ImeTracing.java index a4328cc14aa0..e6a9b543dae2 100644 --- a/core/java/com/android/internal/inputmethod/ImeTracing.java +++ b/core/java/com/android/internal/inputmethod/ImeTracing.java @@ -22,6 +22,7 @@ import android.app.ActivityThread; import android.util.Log; import android.util.proto.ProtoOutputStream; import android.view.inputmethod.InputMethodManager; +import android.view.inputmethod.InputMethodManagerGlobal; import java.io.PrintWriter; @@ -44,7 +45,7 @@ public abstract class ImeTracing { private static ImeTracing sInstance; static boolean sEnabled = false; - private final boolean mIsAvailable = IInputMethodManagerGlobal.isAvailable(); + private final boolean mIsAvailable = InputMethodManagerGlobal.isImeTraceAvailable(); protected boolean mDumpInProgress; protected final Object mDumpInProgressLock = new Object(); @@ -81,7 +82,7 @@ public abstract class ImeTracing { * @param where */ public void sendToService(byte[] protoDump, int source, String where) { - IInputMethodManagerGlobal.startProtoDump(protoDump, source, where, + InputMethodManagerGlobal.startProtoDump(protoDump, source, where, e -> Log.e(TAG, "Exception while sending ime-related dump to server", e)); } @@ -90,7 +91,7 @@ public abstract class ImeTracing { */ @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) public final void startImeTrace() { - IInputMethodManagerGlobal.startImeTrace(e -> Log.e(TAG, "Could not start ime trace.", e)); + InputMethodManagerGlobal.startImeTrace(e -> Log.e(TAG, "Could not start ime trace.", e)); } /** @@ -98,7 +99,7 @@ public abstract class ImeTracing { */ @RequiresPermission(android.Manifest.permission.CONTROL_UI_TRACING) public final void stopImeTrace() { - IInputMethodManagerGlobal.stopImeTrace(e -> Log.e(TAG, "Could not stop ime trace.", e)); + InputMethodManagerGlobal.stopImeTrace(e -> Log.e(TAG, "Could not stop ime trace.", e)); } /** diff --git a/core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java b/core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java index 4caca84d76c7..95ed4ed50971 100644 --- a/core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java +++ b/core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.util.proto.ProtoOutputStream; import android.view.inputmethod.InputMethodManager; +import android.view.inputmethod.InputMethodManagerGlobal; import java.io.PrintWriter; @@ -28,7 +29,7 @@ import java.io.PrintWriter; */ class ImeTracingClientImpl extends ImeTracing { ImeTracingClientImpl() { - sEnabled = IInputMethodManagerGlobal.isImeTraceEnabled(); + sEnabled = InputMethodManagerGlobal.isImeTraceEnabled(); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java index 0bb76b9e61e7..bb7c4134aaaf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java @@ -38,10 +38,10 @@ import android.view.WindowInsets; import android.view.WindowInsets.Type.InsetsType; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; +import android.view.inputmethod.InputMethodManagerGlobal; import androidx.annotation.VisibleForTesting; -import com.android.internal.inputmethod.IInputMethodManagerGlobal; import com.android.wm.shell.sysui.ShellInit; import java.util.ArrayList; @@ -515,7 +515,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged void removeImeSurface() { // Remove the IME surface to make the insets invisible for // non-client controlled insets. - IInputMethodManagerGlobal.removeImeSurface( + InputMethodManagerGlobal.removeImeSurface( e -> Slog.e(TAG, "Failed to remove IME surface.", e)); } diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java index cd9ef0915741..c3313e0d11ca 100644 --- a/services/core/java/com/android/server/dreams/DreamController.java +++ b/services/core/java/com/android/server/dreams/DreamController.java @@ -245,6 +245,7 @@ final class DreamController { if (mSentStartBroadcast) { mContext.sendBroadcastAsUser(mDreamingStoppedIntent, UserHandle.ALL); + mSentStartBroadcast = false; } mActivityTaskManager.removeRootTasksWithActivityTypes( diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index 6e2ccebb6ff4..4ca4817cc4fe 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -23,12 +23,14 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static com.android.server.wm.ActivityInterceptorCallback.DREAM_MANAGER_ORDERED_ID; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.TaskInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -38,6 +40,8 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ServiceInfo; import android.database.ContentObserver; import android.hardware.display.AmbientDisplayConfiguration; +import android.net.Uri; +import android.os.BatteryManager; import android.os.Binder; import android.os.Build; import android.os.Handler; @@ -72,6 +76,8 @@ import com.android.server.wm.ActivityTaskManagerInternal; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -88,6 +94,15 @@ public final class DreamManagerService extends SystemService { private static final String DOZE_WAKE_LOCK_TAG = "dream:doze"; private static final String DREAM_WAKE_LOCK_TAG = "dream:dream"; + /** Constants for the when to activate dreams. */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({DREAM_ON_DOCK, DREAM_ON_CHARGE, DREAM_ON_DOCK_OR_CHARGE}) + public @interface WhenToDream {} + private static final int DREAM_DISABLED = 0x0; + private static final int DREAM_ON_DOCK = 0x1; + private static final int DREAM_ON_CHARGE = 0x2; + private static final int DREAM_ON_DOCK_OR_CHARGE = 0x3; + private final Object mLock = new Object(); private final Context mContext; @@ -101,12 +116,20 @@ public final class DreamManagerService extends SystemService { private final DreamUiEventLogger mDreamUiEventLogger; private final ComponentName mAmbientDisplayComponent; private final boolean mDismissDreamOnActivityStart; + private final boolean mDreamsOnlyEnabledForSystemUser; + private final boolean mDreamsEnabledByDefaultConfig; + private final boolean mDreamsActivatedOnChargeByDefault; + private final boolean mDreamsActivatedOnDockByDefault; @GuardedBy("mLock") private DreamRecord mCurrentDream; private boolean mForceAmbientDisplayEnabled; - private final boolean mDreamsOnlyEnabledForSystemUser; + private SettingsObserver mSettingsObserver; + private boolean mDreamsEnabledSetting; + @WhenToDream private int mWhenToDream; + private boolean mIsDocked; + private boolean mIsCharging; // A temporary dream component that, when present, takes precedence over user configured dream // component. @@ -144,6 +167,37 @@ public final class DreamManagerService extends SystemService { } }; + private final BroadcastReceiver mChargingReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + mIsCharging = (BatteryManager.ACTION_CHARGING.equals(intent.getAction())); + } + }; + + private final BroadcastReceiver mDockStateReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { + int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, + Intent.EXTRA_DOCK_STATE_UNDOCKED); + mIsDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED; + } + } + }; + + private final class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + synchronized (mLock) { + updateWhenToDreamSettings(); + } + } + } + public DreamManagerService(Context context) { super(context); mContext = context; @@ -164,6 +218,14 @@ public final class DreamManagerService extends SystemService { mContext.getResources().getBoolean(R.bool.config_dreamsOnlyEnabledForSystemUser); mDismissDreamOnActivityStart = mContext.getResources().getBoolean( R.bool.config_dismissDreamOnActivityStart); + + mDreamsEnabledByDefaultConfig = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_dreamsEnabledByDefault); + mDreamsActivatedOnChargeByDefault = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_dreamsActivatedOnSleepByDefault); + mDreamsActivatedOnDockByDefault = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault); + mSettingsObserver = new SettingsObserver(mHandler); } @Override @@ -197,6 +259,30 @@ public final class DreamManagerService extends SystemService { DREAM_MANAGER_ORDERED_ID, mActivityInterceptorCallback); } + + mContext.registerReceiver( + mDockStateReceiver, new IntentFilter(Intent.ACTION_DOCK_EVENT)); + IntentFilter chargingIntentFilter = new IntentFilter(); + chargingIntentFilter.addAction(BatteryManager.ACTION_CHARGING); + chargingIntentFilter.addAction(BatteryManager.ACTION_DISCHARGING); + mContext.registerReceiver(mChargingReceiver, chargingIntentFilter); + + mSettingsObserver = new SettingsObserver(mHandler); + mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP), + false, mSettingsObserver, UserHandle.USER_ALL); + mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK), + false, mSettingsObserver, UserHandle.USER_ALL); + mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.SCREENSAVER_ENABLED), + false, mSettingsObserver, UserHandle.USER_ALL); + + // We don't get an initial broadcast for the batter state, so we have to initialize + // directly from BatteryManager. + mIsCharging = mContext.getSystemService(BatteryManager.class).isCharging(); + + updateWhenToDreamSettings(); } } @@ -207,6 +293,14 @@ public final class DreamManagerService extends SystemService { pw.println("mCurrentDream=" + mCurrentDream); pw.println("mForceAmbientDisplayEnabled=" + mForceAmbientDisplayEnabled); pw.println("mDreamsOnlyEnabledForSystemUser=" + mDreamsOnlyEnabledForSystemUser); + pw.println("mDreamsEnabledSetting=" + mDreamsEnabledSetting); + pw.println("mForceAmbientDisplayEnabled=" + mForceAmbientDisplayEnabled); + pw.println("mDreamsOnlyEnabledForSystemUser=" + mDreamsOnlyEnabledForSystemUser); + pw.println("mDreamsActivatedOnDockByDefault=" + mDreamsActivatedOnDockByDefault); + pw.println("mDreamsActivatedOnChargeByDefault=" + mDreamsActivatedOnChargeByDefault); + pw.println("mIsDocked=" + mIsDocked); + pw.println("mIsCharging=" + mIsCharging); + pw.println("mWhenToDream=" + mWhenToDream); pw.println("getDozeComponent()=" + getDozeComponent()); pw.println(); @@ -214,7 +308,28 @@ public final class DreamManagerService extends SystemService { } } - /** Whether a real dream is occurring. */ + private void updateWhenToDreamSettings() { + synchronized (mLock) { + final ContentResolver resolver = mContext.getContentResolver(); + + final int activateWhenCharging = (Settings.Secure.getIntForUser(resolver, + Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, + mDreamsActivatedOnChargeByDefault ? 1 : 0, + UserHandle.USER_CURRENT) != 0) ? DREAM_ON_CHARGE : DREAM_DISABLED; + final int activateWhenDocked = (Settings.Secure.getIntForUser(resolver, + Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, + mDreamsActivatedOnDockByDefault ? 1 : 0, + UserHandle.USER_CURRENT) != 0) ? DREAM_ON_DOCK : DREAM_DISABLED; + mWhenToDream = activateWhenCharging + activateWhenDocked; + + mDreamsEnabledSetting = (Settings.Secure.getIntForUser(resolver, + Settings.Secure.SCREENSAVER_ENABLED, + mDreamsEnabledByDefaultConfig ? 1 : 0, + UserHandle.USER_CURRENT) != 0); + } + } + + /** Whether a real dream is occurring. */ private boolean isDreamingInternal() { synchronized (mLock) { return mCurrentDream != null && !mCurrentDream.isPreview @@ -236,6 +351,30 @@ public final class DreamManagerService extends SystemService { } } + /** Whether dreaming can start given user settings and the current dock/charge state. */ + private boolean canStartDreamingInternal(boolean isScreenOn) { + synchronized (mLock) { + // Can't start dreaming if we are already dreaming. + if (isScreenOn && isDreamingInternal()) { + return false; + } + + if (!mDreamsEnabledSetting) { + return false; + } + + if ((mWhenToDream & DREAM_ON_CHARGE) == DREAM_ON_CHARGE) { + return mIsCharging; + } + + if ((mWhenToDream & DREAM_ON_DOCK) == DREAM_ON_DOCK) { + return mIsDocked; + } + + return false; + } + } + protected void requestStartDreamFromShell() { requestDreamInternal(); } @@ -869,6 +1008,11 @@ public final class DreamManagerService extends SystemService { } @Override + public boolean canStartDreaming(boolean isScreenOn) { + return canStartDreamingInternal(isScreenOn); + } + + @Override public ComponentName getActiveDreamComponent(boolean doze) { return getActiveDreamComponentInternal(doze); } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java index 799ef41f3067..ab223ef3cbeb 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java @@ -4245,7 +4245,6 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt } boolean changed = false; - Set<Permission> needsUpdate = null; synchronized (mLock) { final Iterator<Permission> it = mRegistry.getPermissionTrees().iterator(); while (it.hasNext()) { @@ -4264,26 +4263,6 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt + " that used to be declared by " + bp.getPackageName()); it.remove(); } - if (needsUpdate == null) { - needsUpdate = new ArraySet<>(); - } - needsUpdate.add(bp); - } - } - if (needsUpdate != null) { - for (final Permission bp : needsUpdate) { - final AndroidPackage sourcePkg = - mPackageManagerInt.getPackage(bp.getPackageName()); - final PackageStateInternal sourcePs = - mPackageManagerInt.getPackageStateInternal(bp.getPackageName()); - synchronized (mLock) { - if (sourcePkg != null && sourcePs != null) { - continue; - } - Slog.w(TAG, "Removing dangling permission tree: " + bp.getName() - + " from package " + bp.getPackageName()); - mRegistry.removePermission(bp.getName()); - } } } return changed; diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index c4e122d4497d..98b5c1ba639b 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -256,6 +256,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final int SHORT_PRESS_POWER_GO_HOME = 4; static final int SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME = 5; static final int SHORT_PRESS_POWER_LOCK_OR_SLEEP = 6; + static final int SHORT_PRESS_POWER_DREAM_OR_SLEEP = 7; // must match: config_LongPressOnPowerBehavior in config.xml static final int LONG_PRESS_POWER_NOTHING = 0; @@ -969,7 +970,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior); } else if (count > 3 && count <= getMaxMultiPressPowerCount()) { Slog.d(TAG, "No behavior defined for power press count " + count); - } else if (count == 1 && interactive && !beganFromNonInteractive) { + } else if (count == 1 && interactive) { + if (beganFromNonInteractive) { + // The "screen is off" case, where we might want to start dreaming on power button + // press. + attemptToDreamFromShortPowerButtonPress(false, () -> {}); + return; + } + if (mSideFpsEventHandler.shouldConsumeSinglePress(eventTime)) { Slog.i(TAG, "Suppressing power key because the user is interacting with the " + "fingerprint sensor"); @@ -1018,11 +1026,39 @@ public class PhoneWindowManager implements WindowManagerPolicy { } break; } + case SHORT_PRESS_POWER_DREAM_OR_SLEEP: { + attemptToDreamFromShortPowerButtonPress( + true, + () -> sleepDefaultDisplayFromPowerButton(eventTime, 0)); + break; + } } } } /** + * Attempt to dream from a power button press. + * + * @param isScreenOn Whether the screen is currently on. + * @param noDreamAction The action to perform if dreaming is not possible. + */ + private void attemptToDreamFromShortPowerButtonPress( + boolean isScreenOn, Runnable noDreamAction) { + if (mShortPressOnPowerBehavior != SHORT_PRESS_POWER_DREAM_OR_SLEEP) { + noDreamAction.run(); + return; + } + + final DreamManagerInternal dreamManagerInternal = getDreamManagerInternal(); + if (dreamManagerInternal == null || !dreamManagerInternal.canStartDreaming(isScreenOn)) { + noDreamAction.run(); + return; + } + + dreamManagerInternal.requestDream(); + } + + /** * Sends the default display to sleep as a result of a power button press. * * @return {@code true} if the device was sent to sleep, {@code false} if the device did not @@ -1593,7 +1629,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // If there's a dream running then use home to escape the dream // but don't actually go home. - if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) { + final DreamManagerInternal dreamManagerInternal = getDreamManagerInternal(); + if (dreamManagerInternal != null && dreamManagerInternal.isDreaming()) { mDreamManagerInternal.stopDream(false /*immediate*/, "short press on home" /*reason*/); return; } @@ -2529,6 +2566,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + private DreamManagerInternal getDreamManagerInternal() { + if (mDreamManagerInternal == null) { + // If mDreamManagerInternal is null, attempt to re-fetch it. + mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class); + } + + return mDreamManagerInternal; + } + private void updateWakeGestureListenerLp() { if (shouldEnableWakeGestureLp()) { mWakeGestureListener.requestWakeUpTrigger(); diff --git a/services/tests/mockingservicestests/src/com/android/server/job/restrictions/ThermalStatusRestrictionTest.java b/services/tests/mockingservicestests/src/com/android/server/job/restrictions/ThermalStatusRestrictionTest.java index aa959167b7f1..f88e18b4ced1 100644 --- a/services/tests/mockingservicestests/src/com/android/server/job/restrictions/ThermalStatusRestrictionTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/job/restrictions/ThermalStatusRestrictionTest.java @@ -184,8 +184,10 @@ public class ThermalStatusRestrictionTest { when(mJobSchedulerService.isCurrentlyRunningLocked(jobLowPriorityRunning)).thenReturn(true); when(mJobSchedulerService.isCurrentlyRunningLocked(jobHighPriorityRunning)) .thenReturn(true); - when(mJobSchedulerService.isLongRunningLocked(jobLowPriorityRunningLong)).thenReturn(true); - when(mJobSchedulerService.isLongRunningLocked(jobHighPriorityRunningLong)).thenReturn(true); + when(mJobSchedulerService.isJobInOvertimeLocked(jobLowPriorityRunningLong)) + .thenReturn(true); + when(mJobSchedulerService.isJobInOvertimeLocked(jobHighPriorityRunningLong)) + .thenReturn(true); assertFalse(mThermalStatusRestriction.isJobRestricted(jobMinPriority)); assertFalse(mThermalStatusRestriction.isJobRestricted(jobLowPriority)); |