summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/service/java/com/android/server/JobSchedulerBackgroundThread.java13
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java4
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java404
-rw-r--r--api/current.txt2
-rwxr-xr-xapi/system-current.txt7
-rw-r--r--api/test-current.txt3
-rw-r--r--cmds/statsd/src/condition/CombinationConditionTracker.cpp29
-rw-r--r--cmds/statsd/src/condition/CombinationConditionTracker.h2
-rw-r--r--cmds/statsd/src/condition/ConditionTracker.h8
-rw-r--r--cmds/statsd/src/condition/SimpleConditionTracker.cpp9
-rw-r--r--cmds/statsd/src/condition/SimpleConditionTracker.h2
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp3
-rw-r--r--core/java/android/app/ContextImpl.java13
-rw-r--r--core/java/android/app/IActivityManager.aidl3
-rw-r--r--core/java/android/app/ResourcesManager.java4
-rw-r--r--core/java/android/os/BatteryStats.java2
-rw-r--r--core/java/android/os/IPowerManager.aidl4
-rw-r--r--core/java/android/os/ParcelDuration.aidl (renamed from packages/SystemUI/src/com/android/systemui/onehanded/dagger/OneHandedModule.java)21
-rw-r--r--core/java/android/os/ParcelDuration.java103
-rw-r--r--core/java/android/os/PowerManager.java77
-rw-r--r--core/java/android/provider/DeviceConfig.java7
-rw-r--r--core/java/android/provider/Settings.java44
-rw-r--r--core/java/android/view/InputWindowHandle.java7
-rw-r--r--core/java/android/webkit/PacProcessor.java36
-rw-r--r--core/java/android/webkit/WebViewFactoryProvider.java9
-rw-r--r--core/java/com/android/internal/util/Preconditions.java14
-rw-r--r--core/jni/android_hardware_input_InputWindowHandle.cpp14
-rw-r--r--core/proto/android/providers/settings/global.proto2
-rw-r--r--core/proto/android/server/powermanagerservice.proto10
-rw-r--r--core/res/AndroidManifest.xml5
-rw-r--r--non-updatable-api/current.txt2
-rw-r--r--non-updatable-api/system-current.txt7
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java2
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java3
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java1
-rw-r--r--packages/SystemUI/AndroidManifest.xml1
-rw-r--r--packages/SystemUI/res/layout/notification_conversation_info.xml2
-rw-r--r--packages/SystemUI/res/layout/partial_conversation_info.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java (renamed from packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java)8
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManager.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java (renamed from packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java)16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java18
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java11
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerConstants.java13
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java36
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerShellCommand.java2
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java8
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java7
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java6
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java3
-rw-r--r--services/core/java/com/android/server/power/Notifier.java15
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java154
-rw-r--r--services/core/java/com/android/server/storage/StorageSessionController.java5
-rw-r--r--services/core/java/com/android/server/wm/DragState.java5
-rw-r--r--services/core/java/com/android/server/wm/InputConsumerImpl.java3
-rw-r--r--services/core/java/com/android/server/wm/InputMonitor.java19
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java2
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java14
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java3
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java692
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java36
-rw-r--r--services/tests/servicestests/src/com/android/server/job/MaxJobCountsTest.java70
-rw-r--r--telephony/java/android/telephony/CellIdentityNr.java12
-rw-r--r--telephony/java/android/telephony/CellInfoNr.java14
76 files changed, 1476 insertions, 711 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/JobSchedulerBackgroundThread.java b/apex/jobscheduler/service/java/com/android/server/JobSchedulerBackgroundThread.java
index 91d254d16b09..a413f7b1f3ca 100644
--- a/apex/jobscheduler/service/java/com/android/server/JobSchedulerBackgroundThread.java
+++ b/apex/jobscheduler/service/java/com/android/server/JobSchedulerBackgroundThread.java
@@ -17,10 +17,13 @@
package com.android.server;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Trace;
+import java.util.concurrent.Executor;
+
/**
* Shared singleton background thread.
*
@@ -31,6 +34,7 @@ public final class JobSchedulerBackgroundThread extends HandlerThread {
private static final long SLOW_DELIVERY_THRESHOLD_MS = 30_000;
private static JobSchedulerBackgroundThread sInstance;
private static Handler sHandler;
+ private static Executor sHandlerExecutor;
private JobSchedulerBackgroundThread() {
super("jobscheduler.bg", android.os.Process.THREAD_PRIORITY_BACKGROUND);
@@ -45,6 +49,7 @@ public final class JobSchedulerBackgroundThread extends HandlerThread {
looper.setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
sHandler = new Handler(sInstance.getLooper());
+ sHandlerExecutor = new HandlerExecutor(sHandler);
}
}
@@ -63,4 +68,12 @@ public final class JobSchedulerBackgroundThread extends HandlerThread {
return sHandler;
}
}
+
+ /** Returns the singleton handler executor for JobSchedulerBackgroundThread */
+ public static Executor getExecutor() {
+ synchronized (JobSchedulerBackgroundThread.class) {
+ ensureThreadLocked();
+ return sHandlerExecutor;
+ }
+ }
}
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 a1a5004447a6..b35a7be1f689 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -166,7 +166,7 @@ class JobConcurrencyManager {
// Note: we can't directly do postDelayed(this::rampUpForScreenOn), because
// we need the exact same instance for removeCallbacks().
mHandler.postDelayed(mRampUpForScreenOff,
- mConstants.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.getValue());
+ mConstants.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS);
}
}
}
@@ -189,7 +189,7 @@ class JobConcurrencyManager {
}
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
if ((mLastScreenOffRealtime
- + mConstants.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.getValue())
+ + mConstants.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS)
> now) {
return;
}
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 3234b274eaa7..cf4caea9c487 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -39,7 +39,6 @@ import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -50,7 +49,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.content.pm.ServiceInfo;
-import android.database.ContentObserver;
import android.net.Uri;
import android.os.BatteryStats;
import android.os.BatteryStatsInternal;
@@ -67,11 +65,10 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.os.WorkSource;
-import android.provider.Settings;
+import android.provider.DeviceConfig;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
-import android.util.KeyValueListParser;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -88,6 +85,7 @@ import com.android.internal.util.FrameworkStatsLog;
import com.android.server.AppStateTracker;
import com.android.server.AppStateTrackerImpl;
import com.android.server.DeviceIdleInternal;
+import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
import com.android.server.SystemService.TargetUser;
import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
@@ -329,39 +327,70 @@ public class JobSchedulerService extends com.android.server.SystemService
// -- Pre-allocated temporaries only for use in assignJobsToContextsLocked --
- private class ConstantsObserver extends ContentObserver {
- private ContentResolver mResolver;
-
- public ConstantsObserver(Handler handler) {
- super(handler);
- }
-
- public void start(ContentResolver resolver) {
- mResolver = resolver;
- mResolver.registerContentObserver(Settings.Global.getUriFor(
- Settings.Global.JOB_SCHEDULER_CONSTANTS), false, this);
- updateConstants();
+ private class ConstantsObserver implements DeviceConfig.OnPropertiesChangedListener {
+ public void start() {
+ DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ JobSchedulerBackgroundThread.getExecutor(), this);
+ // Load all the constants.
+ onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_JOB_SCHEDULER));
}
@Override
- public void onChange(boolean selfChange, Uri uri) {
- updateConstants();
- }
-
- private void updateConstants() {
+ public void onPropertiesChanged(DeviceConfig.Properties properties) {
+ boolean apiQuotaScheduleUpdated = false;
+ boolean concurrencyUpdated = false;
synchronized (mLock) {
- try {
- mConstants.updateConstantsLocked(Settings.Global.getString(mResolver,
- Settings.Global.JOB_SCHEDULER_CONSTANTS));
- for (int controller = 0; controller < mControllers.size(); controller++) {
- final StateController sc = mControllers.get(controller);
- sc.onConstantsUpdatedLocked();
+ for (String name : properties.getKeyset()) {
+ if (name == null) {
+ continue;
}
- updateQuotaTracker();
- } catch (IllegalArgumentException e) {
- // Failed to parse the settings string, log this and move on
- // with defaults.
- Slog.e(TAG, "Bad jobscheduler settings", e);
+ switch (name) {
+ case Constants.KEY_ENABLE_API_QUOTAS:
+ case Constants.KEY_API_QUOTA_SCHEDULE_COUNT:
+ case Constants.KEY_API_QUOTA_SCHEDULE_WINDOW_MS:
+ case Constants.KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT:
+ case Constants.KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION:
+ if (!apiQuotaScheduleUpdated) {
+ mConstants.updateApiQuotaConstantsLocked();
+ updateQuotaTracker();
+ apiQuotaScheduleUpdated = true;
+ }
+ break;
+ case Constants.KEY_MIN_READY_NON_ACTIVE_JOBS_COUNT:
+ case Constants.KEY_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS:
+ mConstants.updateBatchingConstantsLocked();
+ break;
+ case Constants.KEY_HEAVY_USE_FACTOR:
+ case Constants.KEY_MODERATE_USE_FACTOR:
+ mConstants.updateUseFactorConstantsLocked();
+ break;
+ case Constants.KEY_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS:
+ if (!concurrencyUpdated) {
+ mConstants.updateConcurrencyConstantsLocked();
+ concurrencyUpdated = true;
+ }
+ break;
+ case Constants.KEY_MIN_LINEAR_BACKOFF_TIME_MS:
+ case Constants.KEY_MIN_EXP_BACKOFF_TIME_MS:
+ mConstants.updateBackoffConstantsLocked();
+ break;
+ case Constants.KEY_CONN_CONGESTION_DELAY_FRAC:
+ case Constants.KEY_CONN_PREFETCH_RELAX_FRAC:
+ mConstants.updateConnectivityConstantsLocked();
+ break;
+ default:
+ // Too many max_job_* strings to list.
+ if (name.startsWith(Constants.KEY_PREFIX_MAX_JOB)
+ && !concurrencyUpdated) {
+ mConstants.updateConcurrencyConstantsLocked();
+ concurrencyUpdated = true;
+ }
+ break;
+ }
+ }
+ for (int controller = 0; controller < mControllers.size(); controller++) {
+ final StateController sc = mControllers.get(controller);
+ sc.onConstantsUpdatedLocked();
}
}
}
@@ -376,53 +405,52 @@ public class JobSchedulerService extends com.android.server.SystemService
}
static class MaxJobCounts {
- private final KeyValueListParser.IntValue mTotal;
- private final KeyValueListParser.IntValue mMaxBg;
- private final KeyValueListParser.IntValue mMinBg;
+ private final int mTotalDefault;
+ private final String mTotalKey;
+ private final int mMaxBgDefault;
+ private final String mMaxBgKey;
+ private final int mMinBgDefault;
+ private final String mMinBgKey;
+ private int mTotal;
+ private int mMaxBg;
+ private int mMinBg;
MaxJobCounts(int totalDefault, String totalKey,
int maxBgDefault, String maxBgKey, int minBgDefault, String minBgKey) {
- mTotal = new KeyValueListParser.IntValue(totalKey, totalDefault);
- mMaxBg = new KeyValueListParser.IntValue(maxBgKey, maxBgDefault);
- mMinBg = new KeyValueListParser.IntValue(minBgKey, minBgDefault);
+ mTotalKey = totalKey;
+ mTotal = mTotalDefault = totalDefault;
+ mMaxBgKey = maxBgKey;
+ mMaxBg = mMaxBgDefault = maxBgDefault;
+ mMinBgKey = minBgKey;
+ mMinBg = mMinBgDefault = minBgDefault;
}
- public void parse(KeyValueListParser parser) {
- mTotal.parse(parser);
- mMaxBg.parse(parser);
- mMinBg.parse(parser);
+ public void update() {
+ mTotal = DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ mTotalKey, mTotalDefault);
+ mMaxBg = DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ mMaxBgKey, mMaxBgDefault);
+ mMinBg = DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ mMinBgKey, mMinBgDefault);
- if (mTotal.getValue() < 1) {
- mTotal.setValue(1);
- } else if (mTotal.getValue() > MAX_JOB_CONTEXTS_COUNT) {
- mTotal.setValue(MAX_JOB_CONTEXTS_COUNT);
- }
+ // Ensure total in the range [1, MAX_JOB_CONTEXTS_COUNT].
+ mTotal = Math.min(Math.max(1, mTotal), MAX_JOB_CONTEXTS_COUNT);
- if (mMaxBg.getValue() < 1) {
- mMaxBg.setValue(1);
- } else if (mMaxBg.getValue() > mTotal.getValue()) {
- mMaxBg.setValue(mTotal.getValue());
- }
- if (mMinBg.getValue() < 0) {
- mMinBg.setValue(0);
- } else {
- if (mMinBg.getValue() > mMaxBg.getValue()) {
- mMinBg.setValue(mMaxBg.getValue());
- }
- if (mMinBg.getValue() >= mTotal.getValue()) {
- mMinBg.setValue(mTotal.getValue() - 1);
- }
- }
+ // Ensure maxBg in the range [1, total].
+ mMaxBg = Math.min(Math.max(1, mMaxBg), mTotal);
+
+ // Ensure minBg in the range [0, min(maxBg, total - 1)]
+ mMinBg = Math.min(Math.max(0, mMinBg), Math.min(mMaxBg, mTotal - 1));
}
/** Total number of jobs to run simultaneously. */
public int getMaxTotal() {
- return mTotal.getValue();
+ return mTotal;
}
/** Max number of BG (== owned by non-TOP apps) jobs to run simultaneously. */
public int getMaxBg() {
- return mMaxBg.getValue();
+ return mMaxBg;
}
/**
@@ -430,20 +458,34 @@ public class JobSchedulerService extends com.android.server.SystemService
* pending, rather than always running the TOTAL number of FG jobs.
*/
public int getMinBg() {
- return mMinBg.getValue();
+ return mMinBg;
}
public void dump(PrintWriter pw, String prefix) {
- mTotal.dump(pw, prefix);
- mMaxBg.dump(pw, prefix);
- mMinBg.dump(pw, prefix);
+ pw.print(prefix);
+ pw.print(mTotalKey);
+ pw.print("=");
+ pw.print(mTotal);
+ pw.println();
+
+ pw.print(prefix);
+ pw.print(mMaxBgKey);
+ pw.print("=");
+ pw.print(mMaxBg);
+ pw.println();
+
+ pw.print(prefix);
+ pw.print(mMinBgKey);
+ pw.print("=");
+ pw.print(mMinBg);
+ pw.println();
}
public void dumpProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
- mTotal.dumpProto(proto, MaxJobCountsProto.TOTAL_JOBS);
- mMaxBg.dumpProto(proto, MaxJobCountsProto.MAX_BG);
- mMinBg.dumpProto(proto, MaxJobCountsProto.MIN_BG);
+ proto.write(MaxJobCountsProto.TOTAL_JOBS, mTotal);
+ proto.write(MaxJobCountsProto.MAX_BG, mMaxBg);
+ proto.write(MaxJobCountsProto.MIN_BG, mMinBg);
proto.end(token);
}
}
@@ -476,23 +518,11 @@ public class JobSchedulerService extends com.android.server.SystemService
}
/**
- * All times are in milliseconds. These constants are kept synchronized with the system
- * global Settings. Any access to this class or its fields should be done while
+ * All times are in milliseconds. Any access to this class or its fields should be done while
* holding the JobSchedulerService.mLock lock.
*/
public static class Constants {
// Key names stored in the settings value.
- // TODO(124466289): remove deprecated flags when we migrate to DeviceConfig
- private static final String DEPRECATED_KEY_MIN_IDLE_COUNT = "min_idle_count";
- private static final String DEPRECATED_KEY_MIN_CHARGING_COUNT = "min_charging_count";
- private static final String DEPRECATED_KEY_MIN_BATTERY_NOT_LOW_COUNT =
- "min_battery_not_low_count";
- private static final String DEPRECATED_KEY_MIN_STORAGE_NOT_LOW_COUNT =
- "min_storage_not_low_count";
- private static final String DEPRECATED_KEY_MIN_CONNECTIVITY_COUNT =
- "min_connectivity_count";
- private static final String DEPRECATED_KEY_MIN_CONTENT_COUNT = "min_content_count";
- private static final String DEPRECATED_KEY_MIN_READY_JOBS_COUNT = "min_ready_jobs_count";
private static final String KEY_MIN_READY_NON_ACTIVE_JOBS_COUNT =
"min_ready_non_active_jobs_count";
private static final String KEY_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS =
@@ -500,28 +530,10 @@ public class JobSchedulerService extends com.android.server.SystemService
private static final String KEY_HEAVY_USE_FACTOR = "heavy_use_factor";
private static final String KEY_MODERATE_USE_FACTOR = "moderate_use_factor";
- // The following values used to be used on P and below. Do not reuse them.
- private static final String DEPRECATED_KEY_FG_JOB_COUNT = "fg_job_count";
- private static final String DEPRECATED_KEY_BG_NORMAL_JOB_COUNT = "bg_normal_job_count";
- private static final String DEPRECATED_KEY_BG_MODERATE_JOB_COUNT = "bg_moderate_job_count";
- private static final String DEPRECATED_KEY_BG_LOW_JOB_COUNT = "bg_low_job_count";
- private static final String DEPRECATED_KEY_BG_CRITICAL_JOB_COUNT = "bg_critical_job_count";
-
- private static final String DEPRECATED_KEY_MAX_STANDARD_RESCHEDULE_COUNT
- = "max_standard_reschedule_count";
- private static final String DEPRECATED_KEY_MAX_WORK_RESCHEDULE_COUNT =
- "max_work_reschedule_count";
- private static final String KEY_MIN_LINEAR_BACKOFF_TIME = "min_linear_backoff_time";
- private static final String KEY_MIN_EXP_BACKOFF_TIME = "min_exp_backoff_time";
- private static final String DEPRECATED_KEY_STANDBY_HEARTBEAT_TIME =
- "standby_heartbeat_time";
- private static final String DEPRECATED_KEY_STANDBY_WORKING_BEATS = "standby_working_beats";
- private static final String DEPRECATED_KEY_STANDBY_FREQUENT_BEATS =
- "standby_frequent_beats";
- private static final String DEPRECATED_KEY_STANDBY_RARE_BEATS = "standby_rare_beats";
+ private static final String KEY_MIN_LINEAR_BACKOFF_TIME_MS = "min_linear_backoff_time_ms";
+ private static final String KEY_MIN_EXP_BACKOFF_TIME_MS = "min_exp_backoff_time_ms";
private static final String KEY_CONN_CONGESTION_DELAY_FRAC = "conn_congestion_delay_frac";
private static final String KEY_CONN_PREFETCH_RELAX_FRAC = "conn_prefetch_relax_frac";
- private static final String DEPRECATED_KEY_USE_HEARTBEATS = "use_heartbeats";
private static final String KEY_ENABLE_API_QUOTAS = "enable_api_quotas";
private static final String KEY_API_QUOTA_SCHEDULE_COUNT = "aq_schedule_count";
private static final String KEY_API_QUOTA_SCHEDULE_WINDOW_MS = "aq_schedule_window_ms";
@@ -530,12 +542,15 @@ public class JobSchedulerService extends com.android.server.SystemService
private static final String KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT =
"aq_schedule_return_failure";
+ private static final String KEY_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS =
+ "screen_off_job_concurrency_increase_delay_ms";
+
private static final int DEFAULT_MIN_READY_NON_ACTIVE_JOBS_COUNT = 5;
private static final long DEFAULT_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = 31 * MINUTE_IN_MILLIS;
private static final float DEFAULT_HEAVY_USE_FACTOR = .9f;
private static final float DEFAULT_MODERATE_USE_FACTOR = .5f;
- private static final long DEFAULT_MIN_LINEAR_BACKOFF_TIME = JobInfo.MIN_BACKOFF_MILLIS;
- private static final long DEFAULT_MIN_EXP_BACKOFF_TIME = JobInfo.MIN_BACKOFF_MILLIS;
+ private static final long DEFAULT_MIN_LINEAR_BACKOFF_TIME_MS = JobInfo.MIN_BACKOFF_MILLIS;
+ private static final long DEFAULT_MIN_EXP_BACKOFF_TIME_MS = JobInfo.MIN_BACKOFF_MILLIS;
private static final float DEFAULT_CONN_CONGESTION_DELAY_FRAC = 0.5f;
private static final float DEFAULT_CONN_PREFETCH_RELAX_FRAC = 0.5f;
private static final boolean DEFAULT_ENABLE_API_QUOTAS = true;
@@ -543,6 +558,7 @@ public class JobSchedulerService extends com.android.server.SystemService
private static final long DEFAULT_API_QUOTA_SCHEDULE_WINDOW_MS = MINUTE_IN_MILLIS;
private static final boolean DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION = true;
private static final boolean DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = false;
+ private static final long DEFAULT_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS = 30_000;
/**
* Minimum # of non-ACTIVE jobs for which the JMS will be happy running some work early.
@@ -564,59 +580,61 @@ public class JobSchedulerService extends com.android.server.SystemService
*/
float MODERATE_USE_FACTOR = DEFAULT_MODERATE_USE_FACTOR;
+ /** Prefix for all of the max_job constants. */
+ private static final String KEY_PREFIX_MAX_JOB = "max_job_";
+
// Max job counts for screen on / off, for each memory trim level.
final MaxJobCountsPerMemoryTrimLevel MAX_JOB_COUNTS_SCREEN_ON =
new MaxJobCountsPerMemoryTrimLevel(
new MaxJobCounts(
- 8, "max_job_total_on_normal",
- 6, "max_job_max_bg_on_normal",
- 2, "max_job_min_bg_on_normal"),
+ 8, KEY_PREFIX_MAX_JOB + "total_on_normal",
+ 6, KEY_PREFIX_MAX_JOB + "max_bg_on_normal",
+ 2, KEY_PREFIX_MAX_JOB + "min_bg_on_normal"),
new MaxJobCounts(
- 8, "max_job_total_on_moderate",
- 4, "max_job_max_bg_on_moderate",
- 2, "max_job_min_bg_on_moderate"),
+ 8, KEY_PREFIX_MAX_JOB + "total_on_moderate",
+ 4, KEY_PREFIX_MAX_JOB + "max_bg_on_moderate",
+ 2, KEY_PREFIX_MAX_JOB + "min_bg_on_moderate"),
new MaxJobCounts(
- 5, "max_job_total_on_low",
- 1, "max_job_max_bg_on_low",
- 1, "max_job_min_bg_on_low"),
+ 5, KEY_PREFIX_MAX_JOB + "total_on_low",
+ 1, KEY_PREFIX_MAX_JOB + "max_bg_on_low",
+ 1, KEY_PREFIX_MAX_JOB + "min_bg_on_low"),
new MaxJobCounts(
- 5, "max_job_total_on_critical",
- 1, "max_job_max_bg_on_critical",
- 1, "max_job_min_bg_on_critical"));
+ 5, KEY_PREFIX_MAX_JOB + "total_on_critical",
+ 1, KEY_PREFIX_MAX_JOB + "max_bg_on_critical",
+ 1, KEY_PREFIX_MAX_JOB + "min_bg_on_critical"));
final MaxJobCountsPerMemoryTrimLevel MAX_JOB_COUNTS_SCREEN_OFF =
new MaxJobCountsPerMemoryTrimLevel(
new MaxJobCounts(
- 10, "max_job_total_off_normal",
- 6, "max_job_max_bg_off_normal",
- 2, "max_job_min_bg_off_normal"),
+ 10, KEY_PREFIX_MAX_JOB + "total_off_normal",
+ 6, KEY_PREFIX_MAX_JOB + "max_bg_off_normal",
+ 2, KEY_PREFIX_MAX_JOB + "min_bg_off_normal"),
new MaxJobCounts(
- 10, "max_job_total_off_moderate",
- 4, "max_job_max_bg_off_moderate",
- 2, "max_job_min_bg_off_moderate"),
+ 10, KEY_PREFIX_MAX_JOB + "total_off_moderate",
+ 4, KEY_PREFIX_MAX_JOB + "max_bg_off_moderate",
+ 2, KEY_PREFIX_MAX_JOB + "min_bg_off_moderate"),
new MaxJobCounts(
- 5, "max_job_total_off_low",
- 1, "max_job_max_bg_off_low",
- 1, "max_job_min_bg_off_low"),
+ 5, KEY_PREFIX_MAX_JOB + "total_off_low",
+ 1, KEY_PREFIX_MAX_JOB + "max_bg_off_low",
+ 1, KEY_PREFIX_MAX_JOB + "min_bg_off_low"),
new MaxJobCounts(
- 5, "max_job_total_off_critical",
- 1, "max_job_max_bg_off_critical",
- 1, "max_job_min_bg_off_critical"));
+ 5, KEY_PREFIX_MAX_JOB + "total_off_critical",
+ 1, KEY_PREFIX_MAX_JOB + "max_bg_off_critical",
+ 1, KEY_PREFIX_MAX_JOB + "min_bg_off_critical"));
/** Wait for this long after screen off before increasing the job concurrency. */
- final KeyValueListParser.IntValue SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS =
- new KeyValueListParser.IntValue(
- "screen_off_job_concurrency_increase_delay_ms", 30_000);
+ long SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS =
+ DEFAULT_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS;
/**
* The minimum backoff time to allow for linear backoff.
*/
- long MIN_LINEAR_BACKOFF_TIME = DEFAULT_MIN_LINEAR_BACKOFF_TIME;
+ long MIN_LINEAR_BACKOFF_TIME_MS = DEFAULT_MIN_LINEAR_BACKOFF_TIME_MS;
/**
* The minimum backoff time to allow for exponential backoff.
*/
- long MIN_EXP_BACKOFF_TIME = DEFAULT_MIN_EXP_BACKOFF_TIME;
+ long MIN_EXP_BACKOFF_TIME_MS = DEFAULT_MIN_EXP_BACKOFF_TIME_MS;
/**
* The fraction of a job's running window that must pass before we
@@ -652,61 +670,78 @@ public class JobSchedulerService extends com.android.server.SystemService
public boolean API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT =
DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT;
- private final KeyValueListParser mParser = new KeyValueListParser(',');
-
- void updateConstantsLocked(String value) {
- try {
- mParser.setString(value);
- } catch (Exception e) {
- // Failed to parse the settings string, log this and move on
- // with defaults.
- Slog.e(TAG, "Bad jobscheduler settings", e);
- }
-
- MIN_READY_NON_ACTIVE_JOBS_COUNT = mParser.getInt(
+ private void updateBatchingConstantsLocked() {
+ MIN_READY_NON_ACTIVE_JOBS_COUNT = DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_JOB_SCHEDULER,
KEY_MIN_READY_NON_ACTIVE_JOBS_COUNT,
DEFAULT_MIN_READY_NON_ACTIVE_JOBS_COUNT);
- MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = mParser.getLong(
+ MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_JOB_SCHEDULER,
KEY_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS,
DEFAULT_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS);
- HEAVY_USE_FACTOR = mParser.getFloat(KEY_HEAVY_USE_FACTOR,
+ }
+
+ private void updateUseFactorConstantsLocked() {
+ HEAVY_USE_FACTOR = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_HEAVY_USE_FACTOR,
DEFAULT_HEAVY_USE_FACTOR);
- MODERATE_USE_FACTOR = mParser.getFloat(KEY_MODERATE_USE_FACTOR,
+ MODERATE_USE_FACTOR = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_MODERATE_USE_FACTOR,
DEFAULT_MODERATE_USE_FACTOR);
+ }
- MAX_JOB_COUNTS_SCREEN_ON.normal.parse(mParser);
- MAX_JOB_COUNTS_SCREEN_ON.moderate.parse(mParser);
- MAX_JOB_COUNTS_SCREEN_ON.low.parse(mParser);
- MAX_JOB_COUNTS_SCREEN_ON.critical.parse(mParser);
+ void updateConcurrencyConstantsLocked() {
+ MAX_JOB_COUNTS_SCREEN_ON.normal.update();
+ MAX_JOB_COUNTS_SCREEN_ON.moderate.update();
+ MAX_JOB_COUNTS_SCREEN_ON.low.update();
+ MAX_JOB_COUNTS_SCREEN_ON.critical.update();
- MAX_JOB_COUNTS_SCREEN_OFF.normal.parse(mParser);
- MAX_JOB_COUNTS_SCREEN_OFF.moderate.parse(mParser);
- MAX_JOB_COUNTS_SCREEN_OFF.low.parse(mParser);
- MAX_JOB_COUNTS_SCREEN_OFF.critical.parse(mParser);
+ MAX_JOB_COUNTS_SCREEN_OFF.normal.update();
+ MAX_JOB_COUNTS_SCREEN_OFF.moderate.update();
+ MAX_JOB_COUNTS_SCREEN_OFF.low.update();
+ MAX_JOB_COUNTS_SCREEN_OFF.critical.update();
- SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.parse(mParser);
+ SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS = DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS,
+ DEFAULT_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS);
+ }
- MIN_LINEAR_BACKOFF_TIME = mParser.getDurationMillis(KEY_MIN_LINEAR_BACKOFF_TIME,
- DEFAULT_MIN_LINEAR_BACKOFF_TIME);
- MIN_EXP_BACKOFF_TIME = mParser.getDurationMillis(KEY_MIN_EXP_BACKOFF_TIME,
- DEFAULT_MIN_EXP_BACKOFF_TIME);
- CONN_CONGESTION_DELAY_FRAC = mParser.getFloat(KEY_CONN_CONGESTION_DELAY_FRAC,
+ private void updateBackoffConstantsLocked() {
+ MIN_LINEAR_BACKOFF_TIME_MS = DeviceConfig.getLong(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_MIN_LINEAR_BACKOFF_TIME_MS,
+ DEFAULT_MIN_LINEAR_BACKOFF_TIME_MS);
+ MIN_EXP_BACKOFF_TIME_MS = DeviceConfig.getLong(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_MIN_EXP_BACKOFF_TIME_MS,
+ DEFAULT_MIN_EXP_BACKOFF_TIME_MS);
+ }
+
+ private void updateConnectivityConstantsLocked() {
+ CONN_CONGESTION_DELAY_FRAC = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_CONN_CONGESTION_DELAY_FRAC,
DEFAULT_CONN_CONGESTION_DELAY_FRAC);
- CONN_PREFETCH_RELAX_FRAC = mParser.getFloat(KEY_CONN_PREFETCH_RELAX_FRAC,
+ CONN_PREFETCH_RELAX_FRAC = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_CONN_PREFETCH_RELAX_FRAC,
DEFAULT_CONN_PREFETCH_RELAX_FRAC);
+ }
- ENABLE_API_QUOTAS = mParser.getBoolean(KEY_ENABLE_API_QUOTAS,
- DEFAULT_ENABLE_API_QUOTAS);
+ private void updateApiQuotaConstantsLocked() {
+ ENABLE_API_QUOTAS = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_ENABLE_API_QUOTAS, DEFAULT_ENABLE_API_QUOTAS);
// Set a minimum value on the quota limit so it's not so low that it interferes with
// legitimate use cases.
API_QUOTA_SCHEDULE_COUNT = Math.max(250,
- mParser.getInt(KEY_API_QUOTA_SCHEDULE_COUNT, DEFAULT_API_QUOTA_SCHEDULE_COUNT));
- API_QUOTA_SCHEDULE_WINDOW_MS = mParser.getDurationMillis(
+ DeviceConfig.getInt(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
+ KEY_API_QUOTA_SCHEDULE_COUNT, DEFAULT_API_QUOTA_SCHEDULE_COUNT));
+ API_QUOTA_SCHEDULE_WINDOW_MS = DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_JOB_SCHEDULER,
KEY_API_QUOTA_SCHEDULE_WINDOW_MS, DEFAULT_API_QUOTA_SCHEDULE_WINDOW_MS);
- API_QUOTA_SCHEDULE_THROW_EXCEPTION = mParser.getBoolean(
+ API_QUOTA_SCHEDULE_THROW_EXCEPTION = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_JOB_SCHEDULER,
KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION,
DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION);
- API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = mParser.getBoolean(
+ API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_JOB_SCHEDULER,
KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT,
DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT);
}
@@ -731,10 +766,11 @@ public class JobSchedulerService extends com.android.server.SystemService
MAX_JOB_COUNTS_SCREEN_OFF.low.dump(pw, "");
MAX_JOB_COUNTS_SCREEN_OFF.critical.dump(pw, "");
- SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.dump(pw, "");
+ pw.print(KEY_SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS,
+ SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS).println();
- pw.print(KEY_MIN_LINEAR_BACKOFF_TIME, MIN_LINEAR_BACKOFF_TIME).println();
- pw.print(KEY_MIN_EXP_BACKOFF_TIME, MIN_EXP_BACKOFF_TIME).println();
+ pw.print(KEY_MIN_LINEAR_BACKOFF_TIME_MS, MIN_LINEAR_BACKOFF_TIME_MS).println();
+ pw.print(KEY_MIN_EXP_BACKOFF_TIME_MS, MIN_EXP_BACKOFF_TIME_MS).println();
pw.print(KEY_CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC).println();
pw.print(KEY_CONN_PREFETCH_RELAX_FRAC, CONN_PREFETCH_RELAX_FRAC).println();
@@ -760,11 +796,11 @@ public class JobSchedulerService extends com.android.server.SystemService
MAX_JOB_COUNTS_SCREEN_ON.dumpProto(proto, ConstantsProto.MAX_JOB_COUNTS_SCREEN_ON);
MAX_JOB_COUNTS_SCREEN_OFF.dumpProto(proto, ConstantsProto.MAX_JOB_COUNTS_SCREEN_OFF);
- SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.dumpProto(proto,
- ConstantsProto.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS);
+ proto.write(ConstantsProto.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS,
+ SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS);
- proto.write(ConstantsProto.MIN_LINEAR_BACKOFF_TIME_MS, MIN_LINEAR_BACKOFF_TIME);
- proto.write(ConstantsProto.MIN_EXP_BACKOFF_TIME_MS, MIN_EXP_BACKOFF_TIME);
+ proto.write(ConstantsProto.MIN_LINEAR_BACKOFF_TIME_MS, MIN_LINEAR_BACKOFF_TIME_MS);
+ proto.write(ConstantsProto.MIN_EXP_BACKOFF_TIME_MS, MIN_EXP_BACKOFF_TIME_MS);
proto.write(ConstantsProto.CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC);
proto.write(ConstantsProto.CONN_PREFETCH_RELAX_FRAC, CONN_PREFETCH_RELAX_FRAC);
@@ -1407,7 +1443,7 @@ public class JobSchedulerService extends com.android.server.SystemService
mHandler = new JobHandler(context.getMainLooper());
mConstants = new Constants();
- mConstantsObserver = new ConstantsObserver(mHandler);
+ mConstantsObserver = new ConstantsObserver();
mJobSchedulerStub = new JobSchedulerStub();
mConcurrencyManager = new JobConcurrencyManager(this);
@@ -1521,7 +1557,7 @@ public class JobSchedulerService extends com.android.server.SystemService
@Override
public void onBootPhase(int phase) {
if (PHASE_SYSTEM_SERVICES_READY == phase) {
- mConstantsObserver.start(getContext().getContentResolver());
+ mConstantsObserver.start();
for (StateController controller : mControllers) {
controller.onSystemServicesReady();
}
@@ -1693,8 +1729,8 @@ public class JobSchedulerService extends com.android.server.SystemService
switch (job.getBackoffPolicy()) {
case JobInfo.BACKOFF_POLICY_LINEAR: {
long backoff = initialBackoffMillis;
- if (backoff < mConstants.MIN_LINEAR_BACKOFF_TIME) {
- backoff = mConstants.MIN_LINEAR_BACKOFF_TIME;
+ if (backoff < mConstants.MIN_LINEAR_BACKOFF_TIME_MS) {
+ backoff = mConstants.MIN_LINEAR_BACKOFF_TIME_MS;
}
delayMillis = backoff * backoffAttempts;
} break;
@@ -1704,8 +1740,8 @@ public class JobSchedulerService extends com.android.server.SystemService
}
case JobInfo.BACKOFF_POLICY_EXPONENTIAL: {
long backoff = initialBackoffMillis;
- if (backoff < mConstants.MIN_EXP_BACKOFF_TIME) {
- backoff = mConstants.MIN_EXP_BACKOFF_TIME;
+ if (backoff < mConstants.MIN_EXP_BACKOFF_TIME_MS) {
+ backoff = mConstants.MIN_EXP_BACKOFF_TIME_MS;
}
delayMillis = (long) Math.scalb(backoff, backoffAttempts - 1);
} break;
diff --git a/api/current.txt b/api/current.txt
index 9e0d88ecdfd1..bf0b0cb67a99 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -36733,9 +36733,11 @@ package android.os {
public final class PowerManager {
method public void addThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
method public void addThermalStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.PowerManager.OnThermalStatusChangedListener);
+ method @Nullable public java.time.Duration getBatteryDischargePrediction();
method public int getCurrentThermalStatus();
method public int getLocationPowerSaveMode();
method public float getThermalHeadroom(@IntRange(from=0, to=60) int);
+ method public boolean isBatteryDischargePredictionPersonalized();
method public boolean isDeviceIdleMode();
method public boolean isIgnoringBatteryOptimizations(String);
method public boolean isInteractive();
diff --git a/api/system-current.txt b/api/system-current.txt
index 3ab164554da6..b4869e3bf0ce 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8394,6 +8394,7 @@ package android.os {
method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplaySuppressedForToken(@NonNull String);
method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSaveEnabled(boolean);
method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSavePolicy(@NonNull android.os.BatterySaverPolicyConfig);
+ method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void setBatteryDischargePrediction(@NonNull java.time.Duration, boolean);
method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public boolean setDynamicPowerSaveHint(boolean, int);
method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setPowerSaveModeEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void suppressAmbientDisplay(@NonNull String, boolean);
@@ -12744,8 +12745,8 @@ package android.webkit {
public interface PacProcessor {
method @Nullable public String findProxyForUrl(@NonNull String);
method @NonNull public static android.webkit.PacProcessor getInstance();
- method @NonNull public static android.webkit.PacProcessor getInstanceForNetwork(long);
- method public default long getNetworkHandle();
+ method @NonNull public static android.webkit.PacProcessor getInstanceForNetwork(@Nullable android.net.Network);
+ method @Nullable public default android.net.Network getNetwork();
method public default void releasePacProcessor();
method public boolean setProxyScript(@NonNull String);
}
@@ -12886,7 +12887,7 @@ package android.webkit {
method public android.webkit.CookieManager getCookieManager();
method public android.webkit.GeolocationPermissions getGeolocationPermissions();
method @NonNull public default android.webkit.PacProcessor getPacProcessor();
- method @NonNull public default android.webkit.PacProcessor getPacProcessorForNetwork(long);
+ method @NonNull public default android.webkit.PacProcessor getPacProcessorForNetwork(@Nullable android.net.Network);
method public android.webkit.ServiceWorkerController getServiceWorkerController();
method public android.webkit.WebViewFactoryProvider.Statics getStatics();
method @Deprecated public android.webkit.TokenBindingService getTokenBindingService();
diff --git a/api/test-current.txt b/api/test-current.txt
index c37c6f79218f..a97a9e88a368 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2799,8 +2799,10 @@ package android.os {
public final class PowerManager {
method @RequiresPermission("android.permission.POWER_SAVER") public int getPowerSaveModeTrigger();
+ method @RequiresPermission("android.permission.DEVICE_POWER") public void setBatteryDischargePrediction(@NonNull java.time.Duration, boolean);
method @RequiresPermission("android.permission.POWER_SAVER") public boolean setDynamicPowerSaveHint(boolean, int);
method @RequiresPermission(anyOf={"android.permission.DEVICE_POWER", "android.permission.POWER_SAVER"}) public boolean setPowerSaveModeEnabled(boolean);
+ field public static final String ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED = "android.os.action.ENHANCED_DISCHARGE_PREDICTION_CHANGED";
field public static final int POWER_SAVE_MODE_TRIGGER_DYNAMIC = 1; // 0x1
field public static final int POWER_SAVE_MODE_TRIGGER_PERCENTAGE = 0; // 0x0
}
@@ -3238,6 +3240,7 @@ package android.provider {
field public static final String NAMESPACE_AUTOFILL = "autofill";
field public static final String NAMESPACE_BIOMETRICS = "biometrics";
field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
+ field public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler";
field public static final String NAMESPACE_PERMISSIONS = "permissions";
field public static final String NAMESPACE_PRIVACY = "privacy";
field public static final String NAMESPACE_ROLLBACK = "rollback";
diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.cpp b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
index 7a1ece94fd3e..3b65f8225ee9 100644
--- a/cmds/statsd/src/condition/CombinationConditionTracker.cpp
+++ b/cmds/statsd/src/condition/CombinationConditionTracker.cpp
@@ -38,9 +38,23 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
const vector<sp<ConditionTracker>>& allConditionTrackers,
const unordered_map<int64_t, int>& conditionIdIndexMap,
vector<bool>& stack,
- vector<ConditionState>& initialConditionCache) {
+ vector<ConditionState>& conditionCache) {
VLOG("Combination predicate init() %lld", (long long)mConditionId);
if (mInitialized) {
+ // All the children are guaranteed to be initialized, but the recursion is needed to
+ // fill the conditionCache properly, since another combination condition or metric
+ // might rely on this. The recursion is needed to compute the current condition.
+
+ // Init is called instead of isConditionMet so that the ConditionKey can be filled with the
+ // default key for sliced conditions, since we do not know all indirect descendants here.
+ for (const int childIndex : mChildren) {
+ if (conditionCache[childIndex] == ConditionState::kNotEvaluated) {
+ allConditionTrackers[childIndex]->init(allConditionConfig, allConditionTrackers,
+ conditionIdIndexMap, stack, conditionCache);
+ }
+ }
+ conditionCache[mIndex] =
+ evaluateCombinationCondition(mChildren, mLogicalOperation, conditionCache);
return true;
}
@@ -74,9 +88,8 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
return false;
}
- bool initChildSucceeded =
- childTracker->init(allConditionConfig, allConditionTrackers, conditionIdIndexMap,
- stack, initialConditionCache);
+ bool initChildSucceeded = childTracker->init(allConditionConfig, allConditionTrackers,
+ conditionIdIndexMap, stack, conditionCache);
if (!initChildSucceeded) {
ALOGW("Child initialization failed %lld ", (long long)child);
@@ -96,10 +109,10 @@ bool CombinationConditionTracker::init(const vector<Predicate>& allConditionConf
childTracker->getAtomMatchingTrackerIndex().end());
}
- mUnSlicedPartCondition = evaluateCombinationCondition(mUnSlicedChildren, mLogicalOperation,
- initialConditionCache);
- initialConditionCache[mIndex] =
- evaluateCombinationCondition(mChildren, mLogicalOperation, initialConditionCache);
+ mUnSlicedPartCondition =
+ evaluateCombinationCondition(mUnSlicedChildren, mLogicalOperation, conditionCache);
+ conditionCache[mIndex] =
+ evaluateCombinationCondition(mChildren, mLogicalOperation, conditionCache);
// unmark this node in the recursion stack.
stack[mIndex] = false;
diff --git a/cmds/statsd/src/condition/CombinationConditionTracker.h b/cmds/statsd/src/condition/CombinationConditionTracker.h
index 39ff0ab03266..a7fac3deaabe 100644
--- a/cmds/statsd/src/condition/CombinationConditionTracker.h
+++ b/cmds/statsd/src/condition/CombinationConditionTracker.h
@@ -33,7 +33,7 @@ public:
bool init(const std::vector<Predicate>& allConditionConfig,
const std::vector<sp<ConditionTracker>>& allConditionTrackers,
const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack,
- std::vector<ConditionState>& initialConditionCache) override;
+ std::vector<ConditionState>& conditionCache) override;
void evaluateCondition(const LogEvent& event,
const std::vector<MatchingState>& eventMatcherValues,
diff --git a/cmds/statsd/src/condition/ConditionTracker.h b/cmds/statsd/src/condition/ConditionTracker.h
index 9da1af427e5f..4e1253506be7 100644
--- a/cmds/statsd/src/condition/ConditionTracker.h
+++ b/cmds/statsd/src/condition/ConditionTracker.h
@@ -46,17 +46,19 @@ public:
// Initialize this ConditionTracker. This initialization is done recursively (DFS). It can also
// be done in the constructor, but we do it separately because (1) easy to return a bool to
// indicate whether the initialization is successful. (2) makes unit test easier.
+ // This function can also be called on config updates, in which case it does nothing other than
+ // fill the condition cache with the current condition.
// allConditionConfig: the list of all Predicate config from statsd_config.
// allConditionTrackers: the list of all ConditionTrackers (this is needed because we may also
// need to call init() on children conditions)
// conditionIdIndexMap: the mapping from condition id to its index.
// stack: a bit map to keep track which nodes have been visited on the stack in the recursion.
- // initialConditionCache: tracks initial conditions of all ConditionTrackers.
+ // conditionCache: tracks initial conditions of all ConditionTrackers. returns the
+ // current condition if called on a config update.
virtual bool init(const std::vector<Predicate>& allConditionConfig,
const std::vector<sp<ConditionTracker>>& allConditionTrackers,
const std::unordered_map<int64_t, int>& conditionIdIndexMap,
- std::vector<bool>& stack,
- std::vector<ConditionState>& initialConditionCache) = 0;
+ std::vector<bool>& stack, std::vector<ConditionState>& conditionCache) = 0;
// evaluate current condition given the new event.
// event: the new log event
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
index efb4d4989425..f45759b6a77e 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
@@ -95,11 +95,14 @@ SimpleConditionTracker::~SimpleConditionTracker() {
bool SimpleConditionTracker::init(const vector<Predicate>& allConditionConfig,
const vector<sp<ConditionTracker>>& allConditionTrackers,
const unordered_map<int64_t, int>& conditionIdIndexMap,
- vector<bool>& stack,
- vector<ConditionState>& initialConditionCache) {
+ vector<bool>& stack, vector<ConditionState>& conditionCache) {
// SimpleConditionTracker does not have dependency on other conditions, thus we just return
// if the initialization was successful.
- initialConditionCache[mIndex] = mInitialValue;
+ ConditionKey conditionKey;
+ if (mSliced) {
+ conditionKey[mConditionId] = DEFAULT_DIMENSION_KEY;
+ }
+ isConditionMet(conditionKey, allConditionTrackers, mSliced, conditionCache);
return mInitialized;
}
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.h b/cmds/statsd/src/condition/SimpleConditionTracker.h
index ea7f87bde2b8..1a9e35e38207 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.h
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.h
@@ -38,7 +38,7 @@ public:
bool init(const std::vector<Predicate>& allConditionConfig,
const std::vector<sp<ConditionTracker>>& allConditionTrackers,
const std::unordered_map<int64_t, int>& conditionIdIndexMap, std::vector<bool>& stack,
- std::vector<ConditionState>& initialConditionCache) override;
+ std::vector<ConditionState>& conditionCache) override;
void evaluateCondition(const LogEvent& event,
const std::vector<MatchingState>& eventMatcherValues,
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index daf67e93557c..e40fbdb250f1 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -303,8 +303,7 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config,
const int conditionTrackerCount = config.predicate_size();
conditionConfigs.reserve(conditionTrackerCount);
allConditionTrackers.reserve(conditionTrackerCount);
- initialConditionCache.reserve(conditionTrackerCount);
- std::fill(initialConditionCache.begin(), initialConditionCache.end(), ConditionState::kUnknown);
+ initialConditionCache.assign(conditionTrackerCount, ConditionState::kNotEvaluated);
for (int i = 0; i < conditionTrackerCount; i++) {
const Predicate& condition = config.predicate(i);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index f6b533434ac2..1b3e865945d1 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -187,6 +187,16 @@ class ContextImpl extends Context {
private static final String XATTR_INODE_CODE_CACHE = "user.inode_code_cache";
/**
+ * Special intent extra that critical system apps can use to hide the notification for a
+ * foreground service. This extra should be placed in the intent passed into {@link
+ * #startForegroundService(Intent)}.
+ *
+ * @hide
+ */
+ private static final String EXTRA_HIDDEN_FOREGROUND_SERVICE =
+ "android.intent.extra.HIDDEN_FOREGROUND_SERVICE";
+
+ /**
* Map from package name, to preference name, to cached preferences.
*/
@GuardedBy("ContextImpl.class")
@@ -1698,9 +1708,12 @@ class ContextImpl extends Context {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
+ final boolean hideForegroundNotification = requireForeground
+ && service.getBooleanExtra(EXTRA_HIDDEN_FOREGROUND_SERVICE, false);
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
+ hideForegroundNotification,
getOpPackageName(), getAttributionTag(), user.getIdentifier());
if (cn != null) {
if (cn.getPackageName().equals("!")) {
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index f37ca61ba69f..0a47248e3b70 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -156,7 +156,8 @@ interface IActivityManager {
boolean refContentProvider(in IBinder connection, int stableDelta, int unstableDelta);
PendingIntent getRunningServiceControlPanel(in ComponentName service);
ComponentName startService(in IApplicationThread caller, in Intent service,
- in String resolvedType, boolean requireForeground, in String callingPackage,
+ in String resolvedType, boolean requireForeground,
+ boolean hideForegroundNotification, in String callingPackage,
in String callingFeatureId, int userId);
@UnsupportedAppUsage
int stopService(in IApplicationThread caller, in Intent service,
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index fb2120e5a35b..1aafe2cc6350 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -825,8 +825,8 @@ public class ResourcesManager {
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES,
"ResourcesManager#createApkAssetsSupplierNotLocked");
try {
- if (Thread.holdsLock(this)) {
- Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName()
+ if (DEBUG && Thread.holdsLock(this)) {
+ Slog.w(TAG, "Calling thread " + Thread.currentThread().getName()
+ " is holding mLock", new Throwable());
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index b0d449769be4..fecfd3c2dc7a 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2954,7 +2954,7 @@ public abstract class BatteryStats implements Parcelable {
* enough current data to make a decision, or the battery is currently
* charging.
*
- * @param curTime The current elepsed realtime in microseconds.
+ * @param curTime The current elapsed realtime in microseconds.
*/
@UnsupportedAppUsage
public abstract long computeBatteryTimeRemaining(long curTime);
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index ce6c0ffbc10b..a92d91bdefc5 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -18,6 +18,7 @@
package android.os;
import android.os.BatterySaverPolicyConfig;
+import android.os.ParcelDuration;
import android.os.PowerSaveState;
import android.os.WorkSource;
@@ -58,6 +59,9 @@ interface IPowerManager
boolean setAdaptivePowerSavePolicy(in BatterySaverPolicyConfig config);
boolean setAdaptivePowerSaveEnabled(boolean enabled);
int getPowerSaveModeTrigger();
+ void setBatteryDischargePrediction(in ParcelDuration timeRemaining, boolean isCustomized);
+ ParcelDuration getBatteryDischargePrediction();
+ boolean isBatteryDischargePredictionPersonalized();
boolean isDeviceIdleMode();
boolean isLightDeviceIdleMode();
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/dagger/OneHandedModule.java b/core/java/android/os/ParcelDuration.aidl
index fe5fa2b5fccd..e1aa109f14ae 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/dagger/OneHandedModule.java
+++ b/core/java/android/os/ParcelDuration.aidl
@@ -14,23 +14,6 @@
* limitations under the License.
*/
-package com.android.systemui.onehanded.dagger;
+package android.os;
-import com.android.systemui.onehanded.OneHandedManager;
-import com.android.systemui.onehanded.OneHandedManagerImpl;
-
-import dagger.Binds;
-import dagger.Module;
-
-/**
- * Dagger Module for One handed.
- */
-@Module
-public abstract class OneHandedModule {
-
- /** Binds OneHandedManager as the default. */
- @Binds
- public abstract OneHandedManager provideOneHandedManager(
- OneHandedManagerImpl oneHandedManagerImpl);
-
-}
+parcelable ParcelDuration cpp_header "android/ParcelDuration.h"; \ No newline at end of file
diff --git a/core/java/android/os/ParcelDuration.java b/core/java/android/os/ParcelDuration.java
new file mode 100644
index 000000000000..37cde3125cb5
--- /dev/null
+++ b/core/java/android/os/ParcelDuration.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 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.os;
+
+import android.annotation.NonNull;
+
+import java.time.Duration;
+
+/**
+ * Parcelable version of {@link Duration} that can be used in binder calls.
+ *
+ * @hide
+ */
+public final class ParcelDuration implements Parcelable {
+
+ private final long mSeconds;
+ private final int mNanos;
+
+ /**
+ * Construct a Duration object using the given millisecond value.
+ *
+ * @hide
+ */
+ public ParcelDuration(long ms) {
+ this(Duration.ofMillis(ms));
+ }
+
+ /**
+ * Wrap a {@link Duration} instance.
+ *
+ * @param duration The {@link Duration} instance to wrap.
+ */
+ public ParcelDuration(@NonNull Duration duration) {
+ mSeconds = duration.getSeconds();
+ mNanos = duration.getNano();
+ }
+
+ private ParcelDuration(@NonNull Parcel parcel) {
+ mSeconds = parcel.readLong();
+ mNanos = parcel.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int parcelableFlags) {
+ parcel.writeLong(mSeconds);
+ parcel.writeInt(mNanos);
+ }
+
+ /**
+ * Returns a {@link Duration} instance that's equivalent to this Duration's length.
+ *
+ * @return a {@link Duration} instance of identical length.
+ */
+ @NonNull
+ public Duration getDuration() {
+ return Duration.ofSeconds(mSeconds, mNanos);
+ }
+
+ @Override
+ @NonNull
+ public String toString() {
+ return getDuration().toString();
+ }
+
+ /**
+ * Creator for Duration.
+ */
+ @NonNull
+ public static final Parcelable.Creator<ParcelDuration> CREATOR =
+ new Parcelable.Creator<ParcelDuration>() {
+
+ @Override
+ @NonNull
+ public ParcelDuration createFromParcel(@NonNull Parcel source) {
+ return new ParcelDuration(source);
+ }
+
+ @Override
+ @NonNull
+ public ParcelDuration[] newArray(int size) {
+ return new ParcelDuration[size];
+ }
+ };
+}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 309805f14eeb..ed38b3ff78e5 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -41,6 +41,7 @@ import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.time.Duration;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicLong;
@@ -1719,6 +1720,70 @@ public final class PowerManager {
}
/**
+ * Allows an app to tell the system how long it believes the battery will last and whether
+ * this estimate is customized based on historical device usage or on a generic configuration.
+ * These estimates will be displayed on system UI surfaces in place of the system computed
+ * value.
+ *
+ * Calling this requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+ *
+ * @param timeRemaining The time remaining as a {@link Duration}.
+ * @param isPersonalized true if personalized based on device usage history, false otherwise.
+ * @throws IllegalStateException if the device is powered or currently charging
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.DEVICE_POWER)
+ public void setBatteryDischargePrediction(@NonNull Duration timeRemaining,
+ boolean isPersonalized) {
+ if (timeRemaining == null) {
+ throw new IllegalArgumentException("time remaining must not be null");
+ }
+ try {
+ mService.setBatteryDischargePrediction(new ParcelDuration(timeRemaining),
+ isPersonalized);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the current battery life remaining estimate.
+ *
+ * @return The estimated battery life remaining as a {@link Duration}. Will be {@code null} if
+ * the device is powered, charging, or an error was encountered.
+ */
+ @Nullable
+ public Duration getBatteryDischargePrediction() {
+ try {
+ final ParcelDuration parcelDuration = mService.getBatteryDischargePrediction();
+ if (parcelDuration == null) {
+ return null;
+ }
+ return parcelDuration.getDuration();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns whether the current battery life remaining estimate is personalized based on device
+ * usage history or not. This value does not take a device's powered or charging state into
+ * account.
+ *
+ * @return A boolean indicating if the current discharge estimate is personalized based on
+ * historical device usage or not.
+ */
+ public boolean isBatteryDischargePredictionPersonalized() {
+ try {
+ return mService.isBatteryDischargePredictionPersonalized();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Get data about the battery saver mode for a specific service
* @param serviceType unique key for the service, one of {@link ServiceType}
* @return Battery saver state data.
@@ -2185,6 +2250,18 @@ public final class PowerManager {
}
/**
+ * Intent that is broadcast when the enhanced battery discharge prediction changes. The new
+ * value can be retrieved via {@link #getBatteryDischargePrediction()}.
+ * This broadcast is only sent to registered receivers.
+ *
+ * @hide
+ */
+ @TestApi
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED =
+ "android.os.action.ENHANCED_DISCHARGE_PREDICTION_CHANGED";
+
+ /**
* Intent that is broadcast when the state of {@link #isPowerSaveMode()} changes.
* This broadcast is only sent to registered receivers.
*/
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index b45a1eba1e2f..859b70382328 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -197,6 +197,13 @@ public final class DeviceConfig {
"intelligence_content_suggestions";
/**
+ * Namespace for JobScheduler configurations.
+ * @hide
+ */
+ @TestApi
+ public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler";
+
+ /**
* Namespace for all media native related features.
*
* @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6903a995bf7b..c302def19298 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -65,6 +65,7 @@ import android.os.Bundle;
import android.os.DropBoxManager;
import android.os.IBinder;
import android.os.LocaleList;
+import android.os.PowerManager;
import android.os.PowerManager.AutoPowerSaveModeTriggers;
import android.os.Process;
import android.os.RemoteCallback;
@@ -11844,36 +11845,6 @@ public final class Settings {
public static final String ALARM_MANAGER_CONSTANTS = "alarm_manager_constants";
/**
- * Job scheduler specific settings.
- * This is encoded as a key=value list, separated by commas. Ex:
- *
- * "min_ready_jobs_count=2,moderate_use_factor=.5"
- *
- * The following keys are supported:
- *
- * <pre>
- * min_idle_count (int)
- * min_charging_count (int)
- * min_connectivity_count (int)
- * min_content_count (int)
- * min_ready_jobs_count (int)
- * heavy_use_factor (float)
- * moderate_use_factor (float)
- * fg_job_count (int)
- * bg_normal_job_count (int)
- * bg_moderate_job_count (int)
- * bg_low_job_count (int)
- * bg_critical_job_count (int)
- * </pre>
- *
- * <p>
- * Type: string
- * @hide
- * @see com.android.server.job.JobSchedulerService.Constants
- */
- public static final String JOB_SCHEDULER_CONSTANTS = "job_scheduler_constants";
-
- /**
* Job scheduler QuotaController specific settings.
* This is encoded as a key=value list, separated by commas. Ex:
*
@@ -12545,18 +12516,23 @@ public final class Settings {
* millis. See {@link #BATTERY_ESTIMATES_LAST_UPDATE_TIME} for the last time this value
* was updated.
*
+ * @deprecated Use {@link PowerManager#getBatteryDischargePrediction()} instead.
* @hide
*/
+ @Deprecated
public static final String TIME_REMAINING_ESTIMATE_MILLIS =
"time_remaining_estimate_millis";
/**
- * A boolean indicating whether {@link #TIME_REMAINING_ESTIMATE_MILLIS} is based customized
- * to the devices usage or using global models. See
+ * A boolean indicating whether {@link #TIME_REMAINING_ESTIMATE_MILLIS} is customized
+ * to the device's usage or using global models. See
* {@link #BATTERY_ESTIMATES_LAST_UPDATE_TIME} for the last time this value was updated.
*
+ * @deprecated Use {@link PowerManager#isBatteryDischargePredictionPersonalized()} instead.
+ *
* @hide
*/
+ @Deprecated
public static final String TIME_REMAINING_ESTIMATE_BASED_ON_USAGE =
"time_remaining_estimate_based_on_usage";
@@ -12565,8 +12541,10 @@ public final class Settings {
* average based on historical drain rates. See {@link #BATTERY_ESTIMATES_LAST_UPDATE_TIME}
* for the last time this value was updated.
*
+ * @deprecated Use {@link PowerManager#getHistoricalDischargeTime()} instead.
* @hide
*/
+ @Deprecated
public static final String AVERAGE_TIME_TO_DISCHARGE = "average_time_to_discharge";
/**
@@ -12575,7 +12553,9 @@ public final class Settings {
* and {@link #AVERAGE_TIME_TO_DISCHARGE} were last updated.
*
* @hide
+ * @deprecated No longer needed due to {@link PowerManager#getBatteryDischargePrediction}.
*/
+ @Deprecated
public static final String BATTERY_ESTIMATES_LAST_UPDATE_TIME =
"battery_estimates_last_update_time";
diff --git a/core/java/android/view/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index e341845277d4..1ef701f732ff 100644
--- a/core/java/android/view/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -70,11 +70,8 @@ public final class InputWindowHandle {
// Window is visible.
public boolean visible;
- // Window can receive keys.
- public boolean canReceiveKeys;
-
- // Window has focus.
- public boolean hasFocus;
+ // Window can be focused.
+ public boolean focusable;
// Window has wallpaper. (window is the current wallpaper target)
public boolean hasWallpaper;
diff --git a/core/java/android/webkit/PacProcessor.java b/core/java/android/webkit/PacProcessor.java
index 7e7b987f72f3..b04105ab1e75 100644
--- a/core/java/android/webkit/PacProcessor.java
+++ b/core/java/android/webkit/PacProcessor.java
@@ -32,6 +32,10 @@ public interface PacProcessor {
/**
* Returns the default PacProcessor instance.
*
+ * <p> There can only be one default {@link PacProcessor} instance.
+ * This method will create a new instance if one did not already exist, or
+ * if the previous instance was released with {@link #releasePacProcessor}.
+ *
* @return the default PacProcessor instance.
*/
@NonNull
@@ -43,14 +47,21 @@ public interface PacProcessor {
* Returns PacProcessor instance associated with the {@link Network}.
* The host resolution is done on this {@link Network}.
*
- * @param networkHandle a handle representing {@link Network} handle.
- * @return PacProcessor instance for the specified network.
- * @see Network#getNetworkHandle
- * @see Network#fromNetworkHandle
+ * <p> There can only be one {@link PacProcessor} instance at a time for each {@link Network}.
+ * This method will create a new instance if one did not already exist, or
+ * if the previous instance was released with {@link #releasePacProcessor}.
+ *
+ * <p> The {@link PacProcessor} instance needs to be released manually with
+ * {@link #releasePacProcessor} when the associated {@link Network} goes away.
+ *
+ * @param network a {@link Network} which this {@link PacProcessor}
+ * will use for host/address resolution.
+ * If {@code null} this method is equivalent to {@link #getInstance}.
+ * @return {@link PacProcessor} instance for the specified network.
*/
@NonNull
- static PacProcessor getInstanceForNetwork(long networkHandle) {
- return WebViewFactory.getProvider().getPacProcessorForNetwork(networkHandle);
+ static PacProcessor getInstanceForNetwork(@Nullable Network network) {
+ return WebViewFactory.getProvider().getPacProcessorForNetwork(network);
}
/**
@@ -73,19 +84,22 @@ public interface PacProcessor {
/**
* Stops support for this {@link PacProcessor} and release its resources.
* No methods of this class must be called after calling this method.
+ *
+ * <p> Released instances will not be reused; a subsequent call to
+ * {@link #getInstance} and {@link #getInstanceForNetwork}
+ * for the same network will create a new instance.
*/
default void releasePacProcessor() {
throw new UnsupportedOperationException("Not implemented");
}
/**
- * Returns a network handle associated with this {@link PacProcessor}.
+ * Returns a {@link Network} associated with this {@link PacProcessor}.
*
- * @return a network handle or 0 if a network is unspecified.
- * @see Network#getNetworkHandle
- * @see Network#fromNetworkHandle
+ * @return an associated {@link Network} or {@code null} if a network is unspecified.
*/
- default long getNetworkHandle() {
+ @Nullable
+ default Network getNetwork() {
throw new UnsupportedOperationException("Not implemented");
}
}
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index f1863e319689..ce999cd5e235 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -17,6 +17,7 @@
package android.webkit;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
@@ -188,13 +189,13 @@ public interface WebViewFactoryProvider {
* Returns PacProcessor instance associated with the {@link Network}.
* The host resolution is done on this {@link Network}.
*
- * @param networkHandle a network handle representing the {@link Network}.
+ * @param network a {@link Network} which needs to be associated
+ * with the returned {@link PacProcessor}.
+ * If {@code null} the method returns default {@link PacProcessor}.
* @return the {@link PacProcessor} instance associated with {@link Network}.
- * @see Network#getNetworkHandle
- * @see Network#fromNetworkHandle
*/
@NonNull
- default PacProcessor getPacProcessorForNetwork(long networkHandle) {
+ default PacProcessor getPacProcessorForNetwork(@Nullable Network network) {
throw new UnsupportedOperationException("Not implemented");
}
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index c82a6564c1d7..937b9426476a 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -200,6 +200,20 @@ public class Preconditions {
}
/**
+ * Ensures the truth of an expression involving whether the calling identity is authorized to
+ * call the calling method.
+ *
+ * @param expression a boolean expression
+ * @param message the message of the security exception to be thrown
+ * @throws SecurityException if {@code expression} is false
+ */
+ public static void checkSecurity(final boolean expression, final String message) {
+ if (!expression) {
+ throw new SecurityException(message);
+ }
+ }
+
+ /**
* Ensures the truth of an expression involving whether the calling user is authorized to
* call the calling method.
*
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index ecdba3fcb023..a0638207a841 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -56,8 +56,7 @@ static struct {
jfieldID scaleFactor;
jfieldID touchableRegion;
jfieldID visible;
- jfieldID canReceiveKeys;
- jfieldID hasFocus;
+ jfieldID focusable;
jfieldID hasWallpaper;
jfieldID paused;
jfieldID trustedOverlay;
@@ -145,10 +144,7 @@ bool NativeInputWindowHandle::updateInfo() {
mInfo.visible = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.visible);
- mInfo.canReceiveKeys = env->GetBooleanField(obj,
- gInputWindowHandleClassInfo.canReceiveKeys);
- mInfo.hasFocus = env->GetBooleanField(obj,
- gInputWindowHandleClassInfo.hasFocus);
+ mInfo.focusable = env->GetBooleanField(obj, gInputWindowHandleClassInfo.focusable);
mInfo.hasWallpaper = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.hasWallpaper);
mInfo.paused = env->GetBooleanField(obj,
@@ -320,11 +316,7 @@ int register_android_view_InputWindowHandle(JNIEnv* env) {
GET_FIELD_ID(gInputWindowHandleClassInfo.visible, clazz,
"visible", "Z");
- GET_FIELD_ID(gInputWindowHandleClassInfo.canReceiveKeys, clazz,
- "canReceiveKeys", "Z");
-
- GET_FIELD_ID(gInputWindowHandleClassInfo.hasFocus, clazz,
- "hasFocus", "Z");
+ GET_FIELD_ID(gInputWindowHandleClassInfo.focusable, clazz, "focusable", "Z");
GET_FIELD_ID(gInputWindowHandleClassInfo.hasWallpaper, clazz,
"hasWallpaper", "Z");
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index d5619ca96fbd..9fccdaf9684f 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -507,7 +507,7 @@ message GlobalSettingsProto {
}
optional IntentFirewall intent_firewall = 65;
- optional SettingProto job_scheduler_constants = 66 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ reserved 66; // job_scheduler_constants
optional SettingProto job_scheduler_quota_controller_constants = 149 [ (android.privacy).dest = DEST_AUTOMATIC ];
reserved 150; // job_scheduler_time_controller_constants
diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto
index 0455d58f498b..a2f2c46cba6a 100644
--- a/core/proto/android/server/powermanagerservice.proto
+++ b/core/proto/android/server/powermanagerservice.proto
@@ -174,6 +174,16 @@ message PowerManagerServiceDumpProto {
optional BatterySaverStateMachineProto battery_saver_state_machine = 50;
// Attentive timeout in ms. The timeout is disabled if it is set to -1.
optional sint32 attentive_timeout_ms = 51;
+ // The time (in the elapsed realtime timebase) at which the battery level will reach 0%. This
+ // is provided as an enhanced estimate and only valid if
+ // last_enhanced_discharge_time_updated_elapsed is greater than 0.
+ optional int64 enhanced_discharge_time_elapsed = 52;
+ // Timestamp (in the elapsed realtime timebase) of last update to enhanced battery estimate
+ // data.
+ optional int64 last_enhanced_discharge_time_updated_elapsed = 53;
+ // Whether or not the current enhanced discharge prediction is personalized based on device
+ // usage or not.
+ optional bool is_enhanced_discharge_prediction_personalized = 54;
}
// A com.android.server.power.PowerManagerService.SuspendBlockerImpl object.
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 32c1e4a1411c..57c1fcf7bfb4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -102,6 +102,7 @@
<protected-broadcast android:name="android.os.action.POWER_SAVE_WHITELIST_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED_INTERNAL" />
+ <protected-broadcast android:name="android.os.action.ENHANCED_DISCHARGE_PREDICTION_CHANGED" />
<!-- @deprecated This is rarely used and will be phased out soon. -->
<protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" />
@@ -5040,6 +5041,10 @@
<permission android:name="android.permission.RESET_APP_ERRORS"
android:protectionLevel="signature" />
+ <!-- @hide Allows an application to create/destroy input consumer. -->
+ <permission android:name="android.permission.INPUT_CONSUMER"
+ android:protectionLevel="signature" />
+
<!-- Attribution for Geofencing service. -->
<attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
<!-- Attribution for Country Detector. -->
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index e90fbd4dead8..2ce11f1d2c39 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -35282,9 +35282,11 @@ package android.os {
public final class PowerManager {
method public void addThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
method public void addThermalStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.PowerManager.OnThermalStatusChangedListener);
+ method @Nullable public java.time.Duration getBatteryDischargePrediction();
method public int getCurrentThermalStatus();
method public int getLocationPowerSaveMode();
method public float getThermalHeadroom(@IntRange(from=0, to=60) int);
+ method public boolean isBatteryDischargePredictionPersonalized();
method public boolean isDeviceIdleMode();
method public boolean isIgnoringBatteryOptimizations(String);
method public boolean isInteractive();
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index 3fd0ee1c8011..bc8517d6180a 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -7298,6 +7298,7 @@ package android.os {
method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplaySuppressedForToken(@NonNull String);
method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSaveEnabled(boolean);
method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSavePolicy(@NonNull android.os.BatterySaverPolicyConfig);
+ method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public void setBatteryDischargePrediction(@NonNull java.time.Duration, boolean);
method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public boolean setDynamicPowerSaveHint(boolean, int);
method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setPowerSaveModeEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void suppressAmbientDisplay(@NonNull String, boolean);
@@ -11585,8 +11586,8 @@ package android.webkit {
public interface PacProcessor {
method @Nullable public String findProxyForUrl(@NonNull String);
method @NonNull public static android.webkit.PacProcessor getInstance();
- method @NonNull public static android.webkit.PacProcessor getInstanceForNetwork(long);
- method public default long getNetworkHandle();
+ method @NonNull public static android.webkit.PacProcessor getInstanceForNetwork(@Nullable android.net.Network);
+ method @Nullable public default android.net.Network getNetwork();
method public default void releasePacProcessor();
method public boolean setProxyScript(@NonNull String);
}
@@ -11727,7 +11728,7 @@ package android.webkit {
method public android.webkit.CookieManager getCookieManager();
method public android.webkit.GeolocationPermissions getGeolocationPermissions();
method @NonNull public default android.webkit.PacProcessor getPacProcessor();
- method @NonNull public default android.webkit.PacProcessor getPacProcessorForNetwork(long);
+ method @NonNull public default android.webkit.PacProcessor getPacProcessorForNetwork(@Nullable android.net.Network);
method public android.webkit.ServiceWorkerController getServiceWorkerController();
method public android.webkit.WebViewFactoryProvider.Statics getStatics();
method @Deprecated public android.webkit.TokenBindingService getTokenBindingService();
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java
index b2f98ecde513..24d9d09d2ca9 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java
@@ -22,7 +22,6 @@ import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.SystemServicesModule;
import com.android.systemui.dagger.SystemUIModule;
-import com.android.systemui.onehanded.dagger.OneHandedModule;
import com.android.systemui.pip.phone.dagger.PipModule;
import dagger.Subcomponent;
@@ -36,7 +35,6 @@ import dagger.Subcomponent;
DependencyProvider.class,
DependencyBinder.class,
PipModule.class,
- OneHandedModule.class,
SystemServicesModule.class,
SystemUIModule.class,
CarSystemUIModule.class,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 66be8dd68283..a29314817a8f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -860,9 +860,6 @@ class SettingsProtoDumpUtil {
p.end(intentFirewallToken);
dumpSetting(s, p,
- Settings.Global.JOB_SCHEDULER_CONSTANTS,
- GlobalSettingsProto.JOB_SCHEDULER_CONSTANTS);
- dumpSetting(s, p,
Settings.Global.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS,
GlobalSettingsProto.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS);
dumpSetting(s, p,
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 0ac3355c4952..f219aecfc9d9 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -309,7 +309,6 @@ public class SettingsBackupTest {
Settings.Global.INSTANT_APP_DEXOPT_ENABLED,
Settings.Global.INTENT_FIREWALL_UPDATE_CONTENT_URL,
Settings.Global.INTENT_FIREWALL_UPDATE_METADATA_URL,
- Settings.Global.JOB_SCHEDULER_CONSTANTS,
Settings.Global.JOB_SCHEDULER_QUOTA_CONTROLLER_CONSTANTS,
Settings.Global.KEEP_PROFILE_IN_BACKGROUND,
Settings.Global.KERNEL_CPU_THREAD_READER,
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4ce9f5a9edc6..af008b996172 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -113,6 +113,7 @@
<uses-permission android:name="android.permission.SET_ORIENTATION" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.MONITOR_INPUT" />
+ <uses-permission android:name="android.permission.INPUT_CONSUMER" />
<!-- DreamManager -->
<uses-permission android:name="android.permission.READ_DREAM_STATE" />
diff --git a/packages/SystemUI/res/layout/notification_conversation_info.xml b/packages/SystemUI/res/layout/notification_conversation_info.xml
index 2c4b937ce95b..fd89c0bf39dd 100644
--- a/packages/SystemUI/res/layout/notification_conversation_info.xml
+++ b/packages/SystemUI/res/layout/notification_conversation_info.xml
@@ -210,7 +210,7 @@
android:clickable="false"
android:focusable="false"
android:ellipsize="end"
- android:maxLines="3"
+ android:maxLines="4"
android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
</com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
diff --git a/packages/SystemUI/res/layout/partial_conversation_info.xml b/packages/SystemUI/res/layout/partial_conversation_info.xml
index 07951705664a..c353d089895c 100644
--- a/packages/SystemUI/res/layout/partial_conversation_info.xml
+++ b/packages/SystemUI/res/layout/partial_conversation_info.xml
@@ -128,6 +128,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
+ android:textDirection="locale"
style="@style/TextAppearance.NotificationImportanceChannelGroup" />
</LinearLayout>
</com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index 7281faf1a2c4..b606201cc803 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -22,7 +22,6 @@ import com.android.systemui.InitController;
import com.android.systemui.SystemUIAppComponentFactory;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardSliceProvider;
-import com.android.systemui.onehanded.dagger.OneHandedModule;
import com.android.systemui.pip.phone.dagger.PipModule;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.InjectionInflationController;
@@ -37,7 +36,6 @@ import dagger.Subcomponent;
DefaultComponentBinder.class,
DependencyProvider.class,
DependencyBinder.class,
- OneHandedModule.class,
PipModule.class,
SystemServicesModule.class,
SystemUIBinder.class,
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java
index 90e7e12b2b47..bb59449d114d 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java
@@ -49,7 +49,7 @@ import javax.inject.Inject;
* Manages and manipulates the one handed states, transitions, and gesture for phones.
*/
@SysUISingleton
-public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
+public class OneHandedController implements Dumpable {
private static final String TAG = "OneHandedManager";
private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
"persist.debug.one_handed_offset_percentage";
@@ -106,7 +106,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
* Constructor of OneHandedManager
*/
@Inject
- public OneHandedManagerImpl(Context context,
+ public OneHandedController(Context context,
CommandQueue commandQueue,
DisplayController displayController,
NavigationModeController navigationModeController,
@@ -137,7 +137,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
*/
// TODO(b/161980408): Should remove extra constructor.
@VisibleForTesting
- OneHandedManagerImpl(Context context,
+ OneHandedController(Context context,
CommandQueue commandQueue,
DisplayController displayController,
OneHandedDisplayAreaOrganizer displayAreaOrganizer,
@@ -194,7 +194,6 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
/**
* Enters one handed mode.
*/
- @Override
public void startOneHanded() {
if (!mDisplayAreaOrganizer.isInOneHanded()) {
final int yOffSet = Math.round(getDisplaySize().y * mOffSetFraction);
@@ -206,7 +205,6 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
/**
* Exits one handed mode.
*/
- @Override
public void stopOneHanded() {
if (mDisplayAreaOrganizer.isInOneHanded()) {
mDisplayAreaOrganizer.scheduleOffset(0, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
index 1420811b9b30..f3be699ab821 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
@@ -103,7 +103,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
}
/**
- * Notified by {@link OneHandedManager}, when user update settings of Enabled or Disabled
+ * Notified by {@link OneHandedController}, when user update settings of Enabled or Disabled
*
* @param isEnabled is one handed settings enabled or not
*/
@@ -264,7 +264,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
}
/**
- * The touch(gesture) events to notify {@link OneHandedManager} start or stop one handed
+ * The touch(gesture) events to notify {@link OneHandedController} start or stop one handed
*/
public interface OneHandedGestureEventCallback {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManager.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManager.java
deleted file mode 100644
index 90187a298cf2..000000000000
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManager.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.onehanded;
-
-/**
- * The base class of OneHandedManager
- */
-public interface OneHandedManager {
-
- /**
- * Set one handed enabled or disabled
- */
- default void setOneHandedEnabled(boolean enabled) {}
-
- /**
- * Set task stack changed to exit
- */
- default void setTaskChangeToExit(boolean enabled) {}
-
- /**
- * Exit one handed mode
- */
- default void stopOneHanded() {}
-
- /**
- * Trigger one handed mode
- */
- default void startOneHanded() {}
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
index 0a7eb1bdada0..8265da6a5f14 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
@@ -63,7 +63,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa
}
/**
- * Notified by {@link OneHandedManagerImpl}, when user update settings of Enabled or Disabled
+ * Notified by {@link OneHandedController}, when user update settings of Enabled or Disabled
*
* @param isEnabled is one handed settings enabled or not
*/
@@ -166,7 +166,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa
}
/**
- * The touch(gesture) events to notify {@link OneHandedManager} start or stop one handed
+ * The touch(gesture) events to notify {@link OneHandedController} start or stop one handed
*/
public interface OneHandedTouchEventCallback {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java
index cebcd4ceabe9..3348a06d5cac 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedUI.java
@@ -59,7 +59,7 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
"com.android.internal.systemui.onehanded.gestural";
private static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
- private final OneHandedManagerImpl mOneHandedManager;
+ private final OneHandedController mOneHandedController;
private final CommandQueue mCommandQueue;
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
private final IOverlayManager mOverlayManager;
@@ -74,8 +74,8 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
OneHandedEvents.writeEvent(enabled
? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_ON
: OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_OFF);
- if (mOneHandedManager != null) {
- mOneHandedManager.setOneHandedEnabled(enabled);
+ if (mOneHandedController != null) {
+ mOneHandedController.setOneHandedEnabled(enabled);
}
// Also checks swipe to notification settings since they all need gesture overlay.
@@ -125,8 +125,8 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_ON
: OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_OFF);
- if (mOneHandedManager != null) {
- mOneHandedManager.setTaskChangeToExit(enabled);
+ if (mOneHandedController != null) {
+ mOneHandedController.setTaskChangeToExit(enabled);
}
}
};
@@ -138,8 +138,8 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
final boolean enabled =
OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
mContext.getContentResolver());
- if (mOneHandedManager != null) {
- mOneHandedManager.setSwipeToNotificationEnabled(enabled);
+ if (mOneHandedController != null) {
+ mOneHandedController.setSwipeToNotificationEnabled(enabled);
}
// Also checks one handed mode settings since they all need gesture overlay.
@@ -152,14 +152,14 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
@Inject
public OneHandedUI(Context context,
CommandQueue commandQueue,
- OneHandedManagerImpl oneHandedManager,
+ OneHandedController oneHandedController,
ScreenLifecycle screenLifecycle) {
super(context);
if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
Log.i(TAG, "Device config SUPPORT_ONE_HANDED_MODE off");
mCommandQueue = null;
- mOneHandedManager = null;
+ mOneHandedController = null;
mOverlayManager = null;
mTimeoutHandler = null;
mScreenLifecycle = null;
@@ -167,7 +167,7 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
}
mCommandQueue = commandQueue;
- mOneHandedManager = oneHandedManager;
+ mOneHandedController = oneHandedController;
mTimeoutHandler = OneHandedTimeoutHandler.get();
mScreenLifecycle = screenLifecycle;
mOverlayManager = IOverlayManager.Stub.asInterface(
@@ -260,13 +260,13 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
}
private void updateSettings() {
- mOneHandedManager.setOneHandedEnabled(OneHandedSettingsUtil
+ mOneHandedController.setOneHandedEnabled(OneHandedSettingsUtil
.getSettingsOneHandedModeEnabled(mContext.getContentResolver()));
mTimeoutHandler.setTimeout(OneHandedSettingsUtil
.getSettingsOneHandedModeTimeout(mContext.getContentResolver()));
- mOneHandedManager.setTaskChangeToExit(OneHandedSettingsUtil
+ mOneHandedController.setTaskChangeToExit(OneHandedSettingsUtil
.getSettingsTapsAppToExit(mContext.getContentResolver()));
- mOneHandedManager.setSwipeToNotificationEnabled(OneHandedSettingsUtil
+ mOneHandedController.setSwipeToNotificationEnabled(OneHandedSettingsUtil
.getSettingsSwipeToNotificationEnabled(mContext.getContentResolver()));
}
@@ -295,7 +295,7 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
* Trigger one handed more
*/
public void startOneHanded() {
- mOneHandedManager.startOneHanded();
+ mOneHandedController.startOneHanded();
OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_IN);
}
@@ -303,7 +303,7 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
* Dismiss one handed more
*/
public void stopOneHanded() {
- mOneHandedManager.stopOneHanded();
+ mOneHandedController.stopOneHanded();
OneHandedEvents.writeEvent(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_OUT);
}
@@ -314,8 +314,8 @@ public class OneHandedUI extends SystemUI implements CommandQueue.Callbacks, Dum
final String innerPrefix = " ";
pw.println(TAG + "one handed states: ");
- if (mOneHandedManager != null) {
- ((OneHandedManagerImpl) mOneHandedManager).dump(fd, pw, args);
+ if (mOneHandedController != null) {
+ mOneHandedController.dump(fd, pw, args);
}
if (mTimeoutHandler != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
index 20fa991dcc1f..6b42f2e07bc3 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
@@ -22,6 +22,7 @@ import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD;
import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER;
import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_OTHER;
import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_OVERVIEW;
+import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_VENDOR_GESTURE;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
@@ -37,6 +38,8 @@ public enum ScreenshotEvent implements UiEventLogger.UiEventEnum {
SCREENSHOT_REQUESTED_OVERVIEW(304),
@UiEvent(doc = "screenshot requested from accessibility actions")
SCREENSHOT_REQUESTED_ACCESSIBILITY_ACTIONS(382),
+ @UiEvent(doc = "screenshot requested from vendor gesture")
+ SCREENSHOT_REQUESTED_VENDOR_GESTURE(638),
@UiEvent(doc = "screenshot requested (other)")
SCREENSHOT_REQUESTED_OTHER(305),
@UiEvent(doc = "screenshot was saved")
@@ -81,6 +84,8 @@ public enum ScreenshotEvent implements UiEventLogger.UiEventEnum {
return ScreenshotEvent.SCREENSHOT_REQUESTED_OVERVIEW;
case SCREENSHOT_ACCESSIBILITY_ACTIONS:
return ScreenshotEvent.SCREENSHOT_REQUESTED_ACCESSIBILITY_ACTIONS;
+ case SCREENSHOT_VENDOR_GESTURE:
+ return ScreenshotEvent.SCREENSHOT_REQUESTED_VENDOR_GESTURE;
case SCREENSHOT_OTHER:
default:
return ScreenshotEvent.SCREENSHOT_REQUESTED_OTHER;
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
index b7bc8c8fb7c4..302301d79c3a 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
@@ -24,7 +24,6 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.SystemServicesModule;
import com.android.systemui.dagger.SystemUIBinder;
import com.android.systemui.dagger.SystemUIModule;
-import com.android.systemui.onehanded.dagger.OneHandedModule;
import dagger.Subcomponent;
@@ -36,7 +35,6 @@ import dagger.Subcomponent;
DefaultComponentBinder.class,
DependencyProvider.class,
DependencyBinder.class,
- OneHandedModule.class,
SystemServicesModule.class,
SystemUIBinder.class,
SystemUIModule.class,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt
index ca8f79d08ef0..da1ec9869d87 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt
@@ -21,6 +21,7 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.Before
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.mock
@@ -59,6 +60,7 @@ public class MediaPlayerDataTest : SysuiTestCase() {
}
@Test
+ @Ignore("Flaky")
fun switchPlayersPlaying() {
val playerIsPlaying1 = mock(MediaControlPanel::class.java)
whenever(playerIsPlaying1.isPlaying).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java
index d7dba5fdf8c8..02d587d90655 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java
@@ -46,9 +46,9 @@ import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class OneHandedManagerImplTest extends OneHandedTestCase {
+public class OneHandedControllerTest extends OneHandedTestCase {
Display mDisplay;
- OneHandedManagerImpl mOneHandedManagerImpl;
+ OneHandedController mOneHandedController;
OneHandedTimeoutHandler mTimeoutHandler;
@Mock
@@ -70,7 +70,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mDisplay = mContext.getDisplay();
- mOneHandedManagerImpl = new OneHandedManagerImpl(
+ mOneHandedController = new OneHandedController(
getContext(),
mCommandQueue,
mMockDisplayController,
@@ -102,7 +102,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
@Test
public void testStartOneHanded() {
- mOneHandedManagerImpl.startOneHanded();
+ mOneHandedController.startOneHanded();
verify(mMockDisplayAreaOrganizer).scheduleOffset(anyInt(), anyInt());
}
@@ -110,7 +110,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
@Test
public void testStopOneHanded() {
when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(false);
- mOneHandedManagerImpl.stopOneHanded();
+ mOneHandedController.stopOneHanded();
verify(mMockDisplayAreaOrganizer, never()).scheduleOffset(anyInt(), anyInt());
}
@@ -122,7 +122,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
@Test
public void testStopOneHanded_shouldRemoveTimer() {
- mOneHandedManagerImpl.stopOneHanded();
+ mOneHandedController.stopOneHanded();
verify(mTimeoutHandler).removeTimer();
}
@@ -130,7 +130,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
@Test
public void testUpdateIsEnabled() {
final boolean enabled = true;
- mOneHandedManagerImpl.setOneHandedEnabled(enabled);
+ mOneHandedController.setOneHandedEnabled(enabled);
verify(mMockTouchHandler, times(2)).onOneHandedEnabled(enabled);
}
@@ -138,7 +138,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
@Test
public void testUpdateSwipeToNotificationIsEnabled() {
final boolean enabled = true;
- mOneHandedManagerImpl.setSwipeToNotificationEnabled(enabled);
+ mOneHandedController.setSwipeToNotificationEnabled(enabled);
verify(mMockTouchHandler, times(2)).onOneHandedEnabled(enabled);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
index 95a230f6511c..756382a6c630 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
@@ -30,8 +30,8 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.systemui.model.SysUiState;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
@@ -48,7 +48,7 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase {
OneHandedTouchHandler mTouchHandler;
OneHandedTutorialHandler mTutorialHandler;
OneHandedGestureHandler mGestureHandler;
- OneHandedManagerImpl mOneHandedManagerImpl;
+ OneHandedController mOneHandedController;
@Mock
CommandQueue mCommandQueue;
@Mock
@@ -66,7 +66,7 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase {
mTutorialHandler = new OneHandedTutorialHandler(mContext);
mGestureHandler = Mockito.spy(new OneHandedGestureHandler(
mContext, mMockDisplayController, mMockNavigationModeController));
- mOneHandedManagerImpl = new OneHandedManagerImpl(
+ mOneHandedController = new OneHandedController(
getContext(),
mCommandQueue,
mMockDisplayController,
@@ -93,15 +93,15 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase {
public void testReceiveNewConfig_whenSetOneHandedEnabled() {
// 1st called at init
verify(mGestureHandler).onOneHandedEnabled(true);
- mOneHandedManagerImpl.setOneHandedEnabled(true);
+ mOneHandedController.setOneHandedEnabled(true);
// 2nd called by setOneHandedEnabled()
verify(mGestureHandler, times(2)).onOneHandedEnabled(true);
}
@Test
public void testOneHandedDisabled_shouldDisposeInputChannel() {
- mOneHandedManagerImpl.setOneHandedEnabled(false);
- mOneHandedManagerImpl.setSwipeToNotificationEnabled(false);
+ mOneHandedController.setOneHandedEnabled(false);
+ mOneHandedController.setSwipeToNotificationEnabled(false);
assertThat(mGestureHandler.mInputMonitor).isNull();
assertThat(mGestureHandler.mInputEventReceiver).isNull();
@@ -111,7 +111,7 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase {
public void testChangeNavBarTo2Button_shouldDisposeInputChannel() {
// 1st called at init
verify(mGestureHandler).onOneHandedEnabled(true);
- mOneHandedManagerImpl.setOneHandedEnabled(true);
+ mOneHandedController.setOneHandedEnabled(true);
// 2nd called by setOneHandedEnabled()
verify(mGestureHandler, times(2)).onOneHandedEnabled(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
index 8ae632dd5a47..3c3ace052e47 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
@@ -28,8 +28,8 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.systemui.model.SysUiState;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
@@ -46,7 +46,7 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase {
OneHandedTouchHandler mTouchHandler;
OneHandedTutorialHandler mTutorialHandler;
OneHandedGestureHandler mGestureHandler;
- OneHandedManagerImpl mOneHandedManagerImpl;
+ OneHandedController mOneHandedController;
@Mock
CommandQueue mCommandQueue;
@Mock
@@ -64,7 +64,7 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase {
mTouchHandler = Mockito.spy(new OneHandedTouchHandler());
mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController,
mMockNavigationModeController);
- mOneHandedManagerImpl = new OneHandedManagerImpl(
+ mOneHandedController = new OneHandedController(
getContext(),
mCommandQueue,
mMockDisplayController,
@@ -88,14 +88,14 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase {
@Test
public void testOneHandedDisabled_shouldDisposeInputChannel() {
- mOneHandedManagerImpl.setOneHandedEnabled(false);
+ mOneHandedController.setOneHandedEnabled(false);
assertThat(mTouchHandler.mInputMonitor).isNull();
assertThat(mTouchHandler.mInputEventReceiver).isNull();
}
@Test
public void testOneHandedEnabled_monitorInputChannel() {
- mOneHandedManagerImpl.setOneHandedEnabled(true);
+ mOneHandedController.setOneHandedEnabled(true);
assertThat(mTouchHandler.mInputMonitor).isNotNull();
assertThat(mTouchHandler.mInputEventReceiver).isNotNull();
}
@@ -104,7 +104,7 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase {
public void testReceiveNewConfig_whenSetOneHandedEnabled() {
// 1st called at init
verify(mTouchHandler).onOneHandedEnabled(true);
- mOneHandedManagerImpl.setOneHandedEnabled(true);
+ mOneHandedController.setOneHandedEnabled(true);
// 2nd called by setOneHandedEnabled()
verify(mTouchHandler, times(2)).onOneHandedEnabled(true);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
index c75a8d2f5454..1bffbf7eb8dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
@@ -24,8 +24,8 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.systemui.model.SysUiState;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.wm.shell.common.DisplayController;
import org.junit.Before;
@@ -42,7 +42,7 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
OneHandedTouchHandler mTouchHandler;
OneHandedTutorialHandler mTutorialHandler;
OneHandedGestureHandler mGestureHandler;
- OneHandedManagerImpl mOneHandedManagerImpl;
+ OneHandedController mOneHandedController;
@Mock
CommandQueue mCommandQueue;
@Mock
@@ -61,7 +61,7 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
mTutorialHandler = Mockito.spy(new OneHandedTutorialHandler(mContext));
mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController,
mMockNavigationModeController);
- mOneHandedManagerImpl = new OneHandedManagerImpl(
+ mOneHandedController = new OneHandedController(
getContext(),
mCommandQueue,
mMockDisplayController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java
index f0e713e42046..ae3df5db30bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedUITest.java
@@ -48,7 +48,7 @@ public class OneHandedUITest extends OneHandedTestCase {
OneHandedUI mOneHandedUI;
ScreenLifecycle mScreenLifecycle;
@Mock
- OneHandedManagerImpl mMockOneHandedManagerImpl;
+ OneHandedController mOneHandedController;
@Mock
OneHandedTimeoutHandler mMockTimeoutHandler;
@@ -59,7 +59,7 @@ public class OneHandedUITest extends OneHandedTestCase {
mScreenLifecycle = new ScreenLifecycle();
mOneHandedUI = new OneHandedUI(mContext,
mCommandQueue,
- mMockOneHandedManagerImpl,
+ mOneHandedController,
mScreenLifecycle);
mOneHandedUI.start();
mKeyguardUpdateMonitor = mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
@@ -74,14 +74,14 @@ public class OneHandedUITest extends OneHandedTestCase {
public void testStartOneHanded() {
mOneHandedUI.startOneHanded();
- verify(mMockOneHandedManagerImpl).startOneHanded();
+ verify(mOneHandedController).startOneHanded();
}
@Test
public void testStopOneHanded() {
mOneHandedUI.stopOneHanded();
- verify(mMockOneHandedManagerImpl).stopOneHanded();
+ verify(mOneHandedController).stopOneHanded();
}
@Test
@@ -89,7 +89,7 @@ public class OneHandedUITest extends OneHandedTestCase {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.TAPS_APP_TO_EXIT, 1);
- verify(mMockOneHandedManagerImpl).setTaskChangeToExit(true);
+ verify(mOneHandedController).setTaskChangeToExit(true);
}
@Test
@@ -97,7 +97,7 @@ public class OneHandedUITest extends OneHandedTestCase {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ONE_HANDED_MODE_ENABLED, 1);
- verify(mMockOneHandedManagerImpl).setOneHandedEnabled(true);
+ verify(mOneHandedController).setOneHandedEnabled(true);
}
@Test
@@ -115,7 +115,7 @@ public class OneHandedUITest extends OneHandedTestCase {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1);
- verify(mMockOneHandedManagerImpl).setSwipeToNotificationEnabled(true);
+ verify(mOneHandedController).setSwipeToNotificationEnabled(true);
}
@Ignore("Clarifying do not receive callback")
@@ -123,14 +123,14 @@ public class OneHandedUITest extends OneHandedTestCase {
public void testKeyguardBouncerShowing_shouldStopOneHanded() {
mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true);
- verify(mMockOneHandedManagerImpl).stopOneHanded();
+ verify(mOneHandedController).stopOneHanded();
}
@Test
public void testScreenTurningOff_shouldStopOneHanded() {
mScreenLifecycle.dispatchScreenTurningOff();
- verify(mMockOneHandedManagerImpl).stopOneHanded();
+ verify(mOneHandedController).stopOneHanded();
}
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 6328cb60cf73..c31d73246ff6 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -453,16 +453,16 @@ public final class ActiveServices {
}
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
- int callingPid, int callingUid, boolean fgRequired, String callingPackage,
- @Nullable String callingFeatureId, final int userId)
+ int callingPid, int callingUid, boolean fgRequired, boolean hideFgNotification,
+ String callingPackage, @Nullable String callingFeatureId, final int userId)
throws TransactionTooLargeException {
return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,
- callingPackage, callingFeatureId, userId, false);
+ hideFgNotification, callingPackage, callingFeatureId, userId, false);
}
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
- int callingPid, int callingUid, boolean fgRequired, String callingPackage,
- @Nullable String callingFeatureId, final int userId,
+ int callingPid, int callingUid, boolean fgRequired, boolean hideFgNotification,
+ String callingPackage, @Nullable String callingFeatureId, final int userId,
boolean allowBackgroundActivityStarts) throws TransactionTooLargeException {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
+ " type=" + resolvedType + " args=" + service.getExtras());
@@ -626,6 +626,7 @@ public final class ActiveServices {
r.startRequested = true;
r.delayedStop = false;
r.fgRequired = fgRequired;
+ r.hideFgNotification = hideFgNotification;
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
service, neededGrants, callingUid));
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index e9539be8b0d5..fede1d2832b8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -89,6 +89,7 @@ final class ActivityManagerConstants extends ContentObserver {
static final String KEY_MEMORY_INFO_THROTTLE_TIME = "memory_info_throttle_time";
static final String KEY_TOP_TO_FGS_GRACE_DURATION = "top_to_fgs_grace_duration";
static final String KEY_PENDINGINTENT_WARNING_THRESHOLD = "pendingintent_warning_threshold";
+ static final String KEY_MIN_CRASH_INTERVAL = "min_crash_interval";
private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000;
@@ -122,6 +123,8 @@ final class ActivityManagerConstants extends ContentObserver {
private static final long DEFAULT_MEMORY_INFO_THROTTLE_TIME = 5*60*1000;
private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000;
private static final int DEFAULT_PENDINGINTENT_WARNING_THRESHOLD = 2000;
+ private static final int DEFAULT_MIN_CRASH_INTERVAL = 2 * 60 * 1000;
+
// Flag stored in the DeviceConfig API.
/**
@@ -281,6 +284,12 @@ final class ActivityManagerConstants extends ContentObserver {
// this long.
public long TOP_TO_FGS_GRACE_DURATION = DEFAULT_TOP_TO_FGS_GRACE_DURATION;
+ /**
+ * The minimum time we allow between crashes, for us to consider this
+ * application to be bad and stop its services and reject broadcasts.
+ */
+ public static int MIN_CRASH_INTERVAL = DEFAULT_MIN_CRASH_INTERVAL;
+
// Indicates whether the activity starts logging is enabled.
// Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED
volatile boolean mFlagActivityStartsLoggingEnabled;
@@ -650,6 +659,8 @@ final class ActivityManagerConstants extends ContentObserver {
DEFAULT_MEMORY_INFO_THROTTLE_TIME);
TOP_TO_FGS_GRACE_DURATION = mParser.getDurationMillis(KEY_TOP_TO_FGS_GRACE_DURATION,
DEFAULT_TOP_TO_FGS_GRACE_DURATION);
+ MIN_CRASH_INTERVAL = mParser.getInt(KEY_MIN_CRASH_INTERVAL,
+ DEFAULT_MIN_CRASH_INTERVAL);
PENDINGINTENT_WARNING_THRESHOLD = mParser.getInt(KEY_PENDINGINTENT_WARNING_THRESHOLD,
DEFAULT_PENDINGINTENT_WARNING_THRESHOLD);
@@ -866,6 +877,8 @@ final class ActivityManagerConstants extends ContentObserver {
pw.println(MEMORY_INFO_THROTTLE_TIME);
pw.print(" "); pw.print(KEY_TOP_TO_FGS_GRACE_DURATION); pw.print("=");
pw.println(TOP_TO_FGS_GRACE_DURATION);
+ pw.print(" "); pw.print(KEY_MIN_CRASH_INTERVAL); pw.print("=");
+ pw.println(MIN_CRASH_INTERVAL);
pw.print(" "); pw.print(KEY_IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES); pw.print("=");
pw.println(Arrays.toString(IMPERCEPTIBLE_KILL_EXEMPT_PROC_STATES.toArray()));
pw.print(" "); pw.print(KEY_IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES); pw.print("=");
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3e600b793385..6e1e3d0a9a9a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1370,6 +1370,10 @@ public class ActivityManagerService extends IActivityManager.Stub
final Injector mInjector;
+ /** The package verifier app. */
+ private String mPackageVerifier;
+ private int mPackageVerifierUid = UserHandle.USER_NULL;
+
static final class ProcessChangeItem {
static final int CHANGE_ACTIVITIES = 1<<0;
static final int CHANGE_FOREGROUND_SERVICES = 1<<1;
@@ -2246,6 +2250,18 @@ public class ActivityManagerService extends IActivityManager.Stub
if (phase == PHASE_SYSTEM_SERVICES_READY) {
mService.mBatteryStatsService.systemServicesReady();
mService.mServices.systemServicesReady();
+ mService.mPackageVerifier = ArrayUtils.firstOrNull(
+ LocalServices.getService(PackageManagerInternal.class).getKnownPackageNames(
+ PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM));
+ if (mService.mPackageVerifier != null) {
+ try {
+ mService.mPackageVerifierUid =
+ getContext().getPackageManager().getPackageUid(
+ mService.mPackageVerifier, UserHandle.USER_SYSTEM);
+ } catch (NameNotFoundException e) {
+ Slog.wtf(TAG, "Package manager couldn't get package verifier uid", e);
+ }
+ }
} else if (phase == PHASE_ACTIVITY_MANAGER_READY) {
mService.startBroadcastObservers();
} else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
@@ -13263,8 +13279,8 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
- String resolvedType, boolean requireForeground, String callingPackage,
- String callingFeatureId, int userId)
+ String resolvedType, boolean requireForeground, boolean hideForegroundNotification,
+ String callingPackage, String callingFeatureId, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
@@ -13276,17 +13292,27 @@ public class ActivityManagerService extends IActivityManager.Stub
throw new IllegalArgumentException("callingPackage cannot be null");
}
+ final int callingUid = Binder.getCallingUid();
+ if (requireForeground && hideForegroundNotification) {
+ if (!UserHandle.isSameApp(callingUid, mPackageVerifierUid)
+ || !callingPackage.equals(mPackageVerifier)) {
+ throw new IllegalArgumentException(
+ "Only the package verifier can hide its foreground service notification");
+ }
+ Slog.i(TAG, "Foreground service notification hiding requested by " + callingPackage);
+ }
+
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
synchronized(this) {
final int callingPid = Binder.getCallingPid();
- final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
- requireForeground, callingPackage, callingFeatureId, userId);
+ requireForeground, hideForegroundNotification,
+ callingPackage, callingFeatureId, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -17670,7 +17696,7 @@ public class ActivityManagerService extends IActivityManager.Stub
ComponentName res;
try {
res = mServices.startServiceLocked(null, service,
- resolvedType, -1, uid, fgRequired, callingPackage,
+ resolvedType, -1, uid, fgRequired, false, callingPackage,
callingFeatureId, userId, allowBackgroundActivityStarts);
} finally {
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 149e3baa90e7..a512cca7bac4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -654,7 +654,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
pw.println("Starting service: " + intent);
pw.flush();
ComponentName cn = mInterface.startService(null, intent, intent.getType(),
- asForeground, SHELL_PACKAGE_NAME, null, mUserId);
+ asForeground, false, SHELL_PACKAGE_NAME, null, mUserId);
if (cn == null) {
err.println("Error: Not found; no service started.");
return -1;
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 2e92ac0fb3d6..5268359df327 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -716,7 +716,7 @@ class AppErrors {
// back in the pending list.
ServiceRecord sr = app.getRunningServiceAt(i);
// If the service was restarted a while ago, then reset crash count, else increment it.
- if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) {
+ if (now > sr.restartTime + ActivityManagerConstants.MIN_CRASH_INTERVAL) {
sr.crashCount = 1;
} else {
sr.crashCount++;
@@ -729,7 +729,7 @@ class AppErrors {
}
}
- if (crashTime != null && now < crashTime + ProcessList.MIN_CRASH_INTERVAL) {
+ if (crashTime != null && now < crashTime + ActivityManagerConstants.MIN_CRASH_INTERVAL) {
// The process crashed again very quickly. If it was a bound foreground service, let's
// try to restart again in a while, otherwise the process loses!
Slog.w(TAG, "Process " + app.processName
@@ -771,7 +771,7 @@ class AppErrors {
data.taskId = affectedTaskId;
}
if (data != null && crashTimePersistent != null
- && now < crashTimePersistent + ProcessList.MIN_CRASH_INTERVAL) {
+ && now < crashTimePersistent + ActivityManagerConstants.MIN_CRASH_INTERVAL) {
data.repeating = true;
}
}
@@ -853,7 +853,7 @@ class AppErrors {
mAppsNotReportingCrashes.contains(proc.info.packageName);
final long now = SystemClock.uptimeMillis();
final boolean shouldThottle = crashShowErrorTime != null
- && now < crashShowErrorTime + ProcessList.MIN_CRASH_INTERVAL;
+ && now < crashShowErrorTime + ActivityManagerConstants.MIN_CRASH_INTERVAL;
if ((mService.mAtmInternal.canShowErrorDialogs() || showBackground)
&& !crashSilenced && !shouldThottle
&& (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 4673ecde7a68..76089f8fba01 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -154,10 +154,6 @@ public final class ProcessList {
static final String ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
"persist.sys.vold_app_data_isolation_enabled";
- // The minimum time we allow between crashes, for us to consider this
- // application to be bad and stop and its services and reject broadcasts.
- static final int MIN_CRASH_INTERVAL = 60 * 1000;
-
// OOM adjustments for processes in various states:
// Uninitialized value for any major or minor adj fields
@@ -4070,7 +4066,8 @@ public final class ProcessList {
boolean enqueueLocked(ProcessRecord app, String reason, int requester) {
// Throttle the killing request for potential bad app to avoid cpu thrashing
Long last = app.isolated ? null : mLastProcessKillTimes.get(app.processName, app.uid);
- if (last != null && SystemClock.uptimeMillis() < last + MIN_CRASH_INTERVAL) {
+ if ((last != null) && (SystemClock.uptimeMillis()
+ < (last + ActivityManagerConstants.MIN_CRASH_INTERVAL))) {
return false;
}
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 66677b67b6aa..5b12c8ce6582 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -104,6 +104,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
boolean whitelistManager; // any bindings to this service have BIND_ALLOW_WHITELIST_MANAGEMENT?
boolean delayed; // are we waiting to start this service in the background?
boolean fgRequired; // is the service required to go foreground after starting?
+ boolean hideFgNotification; // Hide the fg service notification
boolean fgWaiting; // is a timeout for going foreground already scheduled?
boolean isForeground; // is service currently in foreground mode?
int foregroundId; // Notification ID of last foreground req.
@@ -836,6 +837,9 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
}
public void postNotification() {
+ if (hideFgNotification) {
+ return;
+ }
final int appUid = appInfo.uid;
final int appPid = app.pid;
if (foregroundId != 0 && foregroundNoti != null) {
@@ -928,7 +932,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
}
if (localForegroundNoti.getSmallIcon() == null) {
// Notifications whose icon is 0 are defined to not show
- // a notification, silently ignoring it. We don't want to
+ // a notification. We don't want to
// just ignore it, we want to prevent the service from
// being foreground.
throw new RuntimeException("invalid service notification: "
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 9f9235dc852f..04658555f22b 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -6103,7 +6103,8 @@ public class NotificationManagerService extends SystemService {
protected boolean isBlocked(NotificationRecord r, NotificationUsageStats usageStats) {
if (isBlocked(r)) {
if (DBG) {
- Slog.e(TAG, "Suppressing notification from package by user request.");
+ Slog.e(TAG, "Suppressing notification from package " + r.getSbn().getPackageName()
+ + " by user request.");
}
usageStats.registerBlocked(r);
return true;
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 8f0fd607f928..d4375eb2935b 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -94,6 +94,7 @@ public class Notifier {
private static final int MSG_USER_ACTIVITY = 1;
private static final int MSG_BROADCAST = 2;
private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
+ private static final int MSG_BROADCAST_ENHANCED_PREDICTION = 4;
private static final int MSG_PROFILE_TIMED_OUT = 5;
private static final int MSG_WIRED_CHARGING_STARTED = 6;
@@ -701,6 +702,16 @@ public class Notifier {
mPolicy.userActivity();
}
+ void postEnhancedDischargePredictionBroadcast(long delayMs) {
+ mHandler.sendEmptyMessageDelayed(MSG_BROADCAST_ENHANCED_PREDICTION, delayMs);
+ }
+
+ private void sendEnhancedDischargePredictionBroadcast() {
+ Intent intent = new Intent(PowerManager.ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED)
+ .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
private void sendNextBroadcast() {
final int powerState;
synchronized (mLock) {
@@ -872,6 +883,10 @@ public class Notifier {
case MSG_WIRELESS_CHARGING_STARTED:
showWirelessChargingStarted(msg.arg1, msg.arg2);
break;
+ case MSG_BROADCAST_ENHANCED_PREDICTION:
+ removeMessages(MSG_BROADCAST_ENHANCED_PREDICTION);
+ sendEnhancedDischargePredictionBroadcast();
+ break;
case MSG_PROFILE_TIMED_OUT:
lockProfile(msg.arg1);
break;
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 882ed1b7960b..9ff164ac4a7b 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -56,6 +56,7 @@ import android.os.IBinder;
import android.os.IPowerManager;
import android.os.Looper;
import android.os.Message;
+import android.os.ParcelDuration;
import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerManager.WakeData;
@@ -89,11 +90,13 @@ import android.view.Display;
import android.view.KeyEvent;
import com.android.internal.BrightnessSynchronizer;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
+import com.android.internal.util.Preconditions;
import com.android.server.EventLogTags;
import com.android.server.LockGuard;
import com.android.server.RescueParty;
@@ -238,6 +241,18 @@ public final class PowerManagerService extends SystemService
private static final int HALT_MODE_REBOOT = 1;
private static final int HALT_MODE_REBOOT_SAFE_MODE = 2;
+ /**
+ * How stale we'll allow the enhanced discharge prediction values to get before considering them
+ * invalid.
+ */
+ private static final long ENHANCED_DISCHARGE_PREDICTION_TIMEOUT_MS = 30 * 60 * 1000L;
+
+ /**
+ * The minimum amount of time between sending consequent
+ * {@link PowerManager#ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED} broadcasts.
+ */
+ private static final long ENHANCED_DISCHARGE_PREDICTION_BROADCAST_MIN_DELAY_MS = 60 * 1000L;
+
private final Context mContext;
private final ServiceThread mHandlerThread;
private final Handler mHandler;
@@ -380,6 +395,34 @@ public final class PowerManagerService extends SystemService
// The current battery level percentage.
private int mBatteryLevel;
+ /**
+ * The lock that should be held when interacting with {@link #mEnhancedDischargeTimeElapsed},
+ * {@link #mLastEnhancedDischargeTimeUpdatedElapsed}, and
+ * {@link #mEnhancedDischargePredictionIsPersonalized}.
+ */
+ private final Object mEnhancedDischargeTimeLock = new Object();
+
+ /**
+ * The time (in the elapsed realtime timebase) at which the battery level will reach 0%. This
+ * is provided as an enhanced estimate and only valid if
+ * {@link #mLastEnhancedDischargeTimeUpdatedElapsed} is greater than 0.
+ */
+ @GuardedBy("mEnhancedDischargeTimeLock")
+ private long mEnhancedDischargeTimeElapsed;
+
+ /**
+ * Timestamp (in the elapsed realtime timebase) of last update to enhanced battery estimate
+ * data.
+ */
+ @GuardedBy("mEnhancedDischargeTimeLock")
+ private long mLastEnhancedDischargeTimeUpdatedElapsed;
+
+ /**
+ * Whether or not the current enhanced discharge prediction is personalized to the user.
+ */
+ @GuardedBy("mEnhancedDischargeTimeLock")
+ private boolean mEnhancedDischargePredictionIsPersonalized;
+
// The battery level percentage at the time the dream started.
// This is used to terminate a dream and go to sleep if the battery is
// draining faster than it is charging and the user activity timeout has expired.
@@ -3737,6 +3780,13 @@ public final class PowerManagerService extends SystemService
pw.println(" mProximityPositive=" + mProximityPositive);
pw.println(" mBootCompleted=" + mBootCompleted);
pw.println(" mSystemReady=" + mSystemReady);
+ synchronized (mEnhancedDischargeTimeLock) {
+ pw.println(" mEnhancedDischargeTimeElapsed=" + mEnhancedDischargeTimeElapsed);
+ pw.println(" mLastEnhancedDischargeTimeUpdatedElapsed="
+ + mLastEnhancedDischargeTimeUpdatedElapsed);
+ pw.println(" mEnhancedDischargePredictionIsPersonalized="
+ + mEnhancedDischargePredictionIsPersonalized);
+ }
pw.println(" mHalAutoSuspendModeEnabled=" + mHalAutoSuspendModeEnabled);
pw.println(" mHalInteractiveModeEnabled=" + mHalInteractiveModeEnabled);
pw.println(" mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
@@ -3952,6 +4002,16 @@ public final class PowerManagerService extends SystemService
proto.write(PowerManagerServiceDumpProto.IS_PROXIMITY_POSITIVE, mProximityPositive);
proto.write(PowerManagerServiceDumpProto.IS_BOOT_COMPLETED, mBootCompleted);
proto.write(PowerManagerServiceDumpProto.IS_SYSTEM_READY, mSystemReady);
+ synchronized (mEnhancedDischargeTimeLock) {
+ proto.write(PowerManagerServiceDumpProto.ENHANCED_DISCHARGE_TIME_ELAPSED,
+ mEnhancedDischargeTimeElapsed);
+ proto.write(
+ PowerManagerServiceDumpProto.LAST_ENHANCED_DISCHARGE_TIME_UPDATED_ELAPSED,
+ mLastEnhancedDischargeTimeUpdatedElapsed);
+ proto.write(
+ PowerManagerServiceDumpProto.IS_ENHANCED_DISCHARGE_PREDICTION_PERSONALIZED,
+ mEnhancedDischargePredictionIsPersonalized);
+ }
proto.write(
PowerManagerServiceDumpProto.IS_HAL_AUTO_SUSPEND_MODE_ENABLED,
mHalAutoSuspendModeEnabled);
@@ -3959,7 +4019,8 @@ public final class PowerManagerService extends SystemService
PowerManagerServiceDumpProto.IS_HAL_AUTO_INTERACTIVE_MODE_ENABLED,
mHalInteractiveModeEnabled);
- final long activeWakeLocksToken = proto.start(PowerManagerServiceDumpProto.ACTIVE_WAKE_LOCKS);
+ final long activeWakeLocksToken = proto.start(
+ PowerManagerServiceDumpProto.ACTIVE_WAKE_LOCKS);
proto.write(
PowerManagerServiceDumpProto.ActiveWakeLocksProto.IS_CPU,
(mWakeLockSummary & WAKE_LOCK_CPU) != 0);
@@ -4262,6 +4323,7 @@ public final class PowerManagerService extends SystemService
if (wcd != null) {
wcd.dumpDebug(proto, PowerManagerServiceDumpProto.WIRELESS_CHARGER_DETECTOR);
}
+
proto.flush();
}
@@ -5022,6 +5084,96 @@ public final class PowerManagerService extends SystemService
}
@Override // Binder call
+ public void setBatteryDischargePrediction(@NonNull ParcelDuration timeRemaining,
+ boolean isPersonalized) {
+ // Get current time before acquiring the lock so that the calculated end time is as
+ // accurate as possible.
+ final long nowElapsed = SystemClock.elapsedRealtime();
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+ final long timeRemainingMs = timeRemaining.getDuration().toMillis();
+ // A non-positive number means the battery should be dead right now...
+ Preconditions.checkArgumentPositive(timeRemainingMs,
+ "Given time remaining is not positive: " + timeRemainingMs);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ if (mIsPowered) {
+ throw new IllegalStateException(
+ "Discharge prediction can't be set while the device is charging");
+ }
+ }
+
+ final long broadcastDelayMs;
+ synchronized (mEnhancedDischargeTimeLock) {
+ if (mLastEnhancedDischargeTimeUpdatedElapsed > nowElapsed) {
+ // Another later call made it into the block first. Keep the latest info.
+ return;
+ }
+ broadcastDelayMs = Math.max(0,
+ ENHANCED_DISCHARGE_PREDICTION_BROADCAST_MIN_DELAY_MS
+ - (nowElapsed - mLastEnhancedDischargeTimeUpdatedElapsed));
+
+ // No need to persist the discharge prediction values since they'll most likely
+ // be wrong immediately after a reboot anyway.
+ mEnhancedDischargeTimeElapsed = nowElapsed + timeRemainingMs;
+ mEnhancedDischargePredictionIsPersonalized = isPersonalized;
+ mLastEnhancedDischargeTimeUpdatedElapsed = nowElapsed;
+ }
+ mNotifier.postEnhancedDischargePredictionBroadcast(broadcastDelayMs);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ private boolean isEnhancedDischargePredictionValidLocked(long nowElapsed) {
+ return mLastEnhancedDischargeTimeUpdatedElapsed > 0
+ && nowElapsed < mEnhancedDischargeTimeElapsed
+ && nowElapsed - mLastEnhancedDischargeTimeUpdatedElapsed
+ < ENHANCED_DISCHARGE_PREDICTION_TIMEOUT_MS;
+ }
+
+ @Override // Binder call
+ public ParcelDuration getBatteryDischargePrediction() {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ if (mIsPowered) {
+ return null;
+ }
+ }
+ synchronized (mEnhancedDischargeTimeLock) {
+ // Get current time after acquiring the lock so that the calculated duration
+ // is as accurate as possible.
+ final long nowElapsed = SystemClock.elapsedRealtime();
+ if (isEnhancedDischargePredictionValidLocked(nowElapsed)) {
+ return new ParcelDuration(mEnhancedDischargeTimeElapsed - nowElapsed);
+ }
+ }
+ return new ParcelDuration(mBatteryStats.computeBatteryTimeRemaining());
+ } catch (RemoteException e) {
+ // Shouldn't happen in-process.
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ return null;
+ }
+
+ @Override // Binder call
+ public boolean isBatteryDischargePredictionPersonalized() {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mEnhancedDischargeTimeLock) {
+ return isEnhancedDischargePredictionValidLocked(SystemClock.elapsedRealtime())
+ && mEnhancedDischargePredictionIsPersonalized;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
public boolean isDeviceIdleMode() {
final long ident = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index 6dc1d6921dbb..0abeac890df1 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -336,11 +336,12 @@ public final class StorageSessionController {
}
/**
- * Returns {@code true} if {@code vol} is an emulated or public volume,
+ * Returns {@code true} if {@code vol} is an emulated or visible public volume,
* {@code false} otherwise
**/
public static boolean isEmulatedOrPublic(VolumeInfo vol) {
- return vol.type == VolumeInfo.TYPE_EMULATED || vol.type == VolumeInfo.TYPE_PUBLIC;
+ return vol.type == VolumeInfo.TYPE_EMULATED
+ || (vol.type == VolumeInfo.TYPE_PUBLIC && vol.isVisible());
}
/** Exception thrown when communication with the {@link ExternalStorageService} fails. */
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 133b11116460..c9f463b8fbeb 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -283,8 +283,9 @@ class DragState {
mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
mDragWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
mDragWindowHandle.visible = true;
- mDragWindowHandle.canReceiveKeys = false;
- mDragWindowHandle.hasFocus = true;
+ // Allows the system to consume keys when dragging is active. This can also be used to
+ // modify the drag state on key press. Example, cancel drag on escape key.
+ mDragWindowHandle.focusable = true;
mDragWindowHandle.hasWallpaper = false;
mDragWindowHandle.paused = false;
mDragWindowHandle.ownerPid = Process.myPid();
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 3b24584b0357..a79d3bb00907 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -80,8 +80,7 @@ class InputConsumerImpl implements IBinder.DeathRecipient {
mWindowHandle.layoutParamsFlags = 0;
mWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
mWindowHandle.visible = true;
- mWindowHandle.canReceiveKeys = false;
- mWindowHandle.hasFocus = false;
+ mWindowHandle.focusable = false;
mWindowHandle.hasWallpaper = false;
mWindowHandle.paused = false;
mWindowHandle.ownerPid = Process.myPid();
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 0fe9735c9e46..16c4942ee972 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -227,6 +227,11 @@ final class InputMonitor {
WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name,
InputEventReceiver.Factory inputEventReceiverFactory) {
+ if (!name.contentEquals(INPUT_CONSUMER_NAVIGATION)) {
+ throw new IllegalArgumentException("Illegal input consumer : " + name
+ + ", display: " + mDisplayId);
+ }
+
if (mInputConsumers.containsKey(name)) {
throw new IllegalStateException("Existing input consumer found with name: " + name
+ ", display: " + mDisplayId);
@@ -256,6 +261,11 @@ final class InputMonitor {
// stack, and we need FLAG_NOT_TOUCH_MODAL to ensure other events fall through
consumer.mWindowHandle.layoutParamsFlags |= FLAG_NOT_TOUCH_MODAL;
break;
+ case INPUT_CONSUMER_RECENTS_ANIMATION:
+ break;
+ default:
+ throw new IllegalArgumentException("Illegal input consumer : " + name
+ + ", display: " + mDisplayId);
}
addInputConsumer(name, consumer);
}
@@ -271,8 +281,7 @@ final class InputMonitor {
inputWindowHandle.layoutParamsType = type;
inputWindowHandle.dispatchingTimeoutMillis = child.getInputDispatchingTimeoutMillis();
inputWindowHandle.visible = isVisible;
- inputWindowHandle.canReceiveKeys = child.canReceiveKeys();
- inputWindowHandle.hasFocus = hasFocus;
+ inputWindowHandle.focusable = hasFocus;
inputWindowHandle.hasWallpaper = hasWallpaper;
inputWindowHandle.paused = child.mActivityRecord != null ? child.mActivityRecord.paused : false;
inputWindowHandle.ownerPid = child.mSession.mPid;
@@ -463,9 +472,6 @@ final class InputMonitor {
mDisplayContent.forAllWindows(this,
true /* traverseTopToBottom */);
- if (mAddWallpaperInputConsumerHandle) {
- mWallpaperInputConsumer.show(mInputTransaction, 0);
- }
if (!mUpdateInputWindowsImmediately) {
mDisplayContent.getPendingTransaction().merge(mInputTransaction);
mDisplayContent.scheduleAnimation();
@@ -572,8 +578,7 @@ final class InputMonitor {
inputWindowHandle.layoutParamsType = type;
inputWindowHandle.dispatchingTimeoutMillis = 0; // it should never receive input
inputWindowHandle.visible = isVisible;
- inputWindowHandle.canReceiveKeys = false;
- inputWindowHandle.hasFocus = false;
+ inputWindowHandle.focusable = false;
inputWindowHandle.inputFeatures = INPUT_FEATURE_NO_INPUT_CHANNEL;
inputWindowHandle.scaleFactor = 1;
inputWindowHandle.layoutParamsFlags =
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 143fbb0fe48b..6882dc4ca151 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -821,7 +821,7 @@ public class RecentsAnimationController implements DeathRecipient {
: null;
if (targetAppMainWindow != null) {
targetAppMainWindow.getBounds(mTmpRect);
- inputWindowHandle.hasFocus = hasFocus;
+ inputWindowHandle.focusable = hasFocus;
inputWindowHandle.touchableRegion.set(mTmpRect);
return true;
}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index a66cd846e8be..f32781a8fcb8 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -242,8 +242,8 @@ class TaskPositioner implements IBinder.DeathRecipient {
mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
mDragWindowHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
mDragWindowHandle.visible = true;
- mDragWindowHandle.canReceiveKeys = false;
- mDragWindowHandle.hasFocus = true;
+ // When dragging the window around, we do not want to steal focus for the window.
+ mDragWindowHandle.focusable = false;
mDragWindowHandle.hasWallpaper = false;
mDragWindowHandle.paused = false;
mDragWindowHandle.ownerPid = Process.myPid();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 32251976eba1..2ce16b2fdd79 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
+import static android.Manifest.permission.INPUT_CONSUMER;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.Manifest.permission.MANAGE_APP_TOKENS;
@@ -5861,6 +5862,11 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void createInputConsumer(IBinder token, String name, int displayId,
InputChannel inputChannel) {
+ if (!mAtmInternal.isCallerRecents(Binder.getCallingUid())
+ && mContext.checkCallingOrSelfPermission(INPUT_CONSUMER) != PERMISSION_GRANTED) {
+ throw new SecurityException("createInputConsumer requires INPUT_CONSUMER permission");
+ }
+
synchronized (mGlobalLock) {
DisplayContent display = mRoot.getDisplayContent(displayId);
if (display != null) {
@@ -5872,6 +5878,11 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public boolean destroyInputConsumer(String name, int displayId) {
+ if (!mAtmInternal.isCallerRecents(Binder.getCallingUid())
+ && mContext.checkCallingOrSelfPermission(INPUT_CONSUMER) != PERMISSION_GRANTED) {
+ throw new SecurityException("destroyInputConsumer requires INPUT_CONSUMER permission");
+ }
+
synchronized (mGlobalLock) {
DisplayContent display = mRoot.getDisplayContent(displayId);
if (display != null) {
@@ -8065,8 +8076,7 @@ public class WindowManagerService extends IWindowManager.Stub
h.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | sanitizedFlags;
h.layoutParamsType = type;
h.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
- h.canReceiveKeys = false;
- h.hasFocus = false;
+ h.focusable = false;
h.hasWallpaper = false;
h.paused = false;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 92177abbbf85..4ff985f6bd43 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -38,6 +38,7 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
@@ -1327,7 +1328,7 @@ class WindowStateAnimator {
mWin.getDisplayContent().adjustForImeIfNeeded();
}
- return mWin.isAnimating(PARENTS);
+ return mWin.isAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION);
}
void dumpDebug(ProtoOutputStream proto, long fieldId) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6154bef2bda3..e49c5abf59f3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1566,7 +1566,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
/**
* Creates a new {@link CallerIdentity} object to represent the caller's identity.
*/
- private CallerIdentity getCallerIdentity(String callerPackage) {
+ private CallerIdentity getCallerIdentity() {
+ final int callerUid = mInjector.binderGetCallingUid();
+ return new CallerIdentity(callerUid, null, null);
+ }
+
+ /**
+ * Creates a new {@link CallerIdentity} object to represent the caller's identity.
+ */
+ private CallerIdentity getCallerIdentity(@NonNull String callerPackage) {
final int callerUid = mInjector.binderGetCallingUid();
if (!isCallingFromPackage(callerPackage, callerUid)) {
@@ -2127,6 +2135,81 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
reqPolicy, /* permission= */ null);
}
+ @NonNull ActiveAdmin getDeviceOwnerOfCallerLocked(final CallerIdentity caller) {
+ ensureLocked();
+ ComponentName doComponent = mOwners.getDeviceOwnerComponent();
+ Preconditions.checkState(doComponent != null,
+ String.format("No device owner for user %d", caller.getUid()));
+
+ // Use the user ID of the caller instead of mOwners.getDeviceOwnerUserId() because
+ // secondary, affiliated users will have their own admin.
+ ActiveAdmin doAdmin = getUserData(caller.getUserId()).mAdminMap.get(doComponent);
+ Preconditions.checkState(doAdmin != null,
+ String.format("Device owner %s for user %d not found", doComponent,
+ caller.getUid()));
+
+ Preconditions.checkSecurity(doAdmin.getUid() == caller.getUid(),
+ String.format("Admin %s is not owned by uid %d, but uid %d", doComponent,
+ caller.getUid(), doAdmin.getUid()));
+
+ Preconditions.checkSecurity(doAdmin.info.getComponent().equals(caller.getComponentName()),
+ String.format("Caller component %s is not device owner",
+ caller.getComponentName()));
+
+ return doAdmin;
+ }
+
+ @NonNull ActiveAdmin getProfileOwnerOfCallerLocked(final CallerIdentity caller) {
+ ensureLocked();
+ final ComponentName poAdminComponent = mOwners.getProfileOwnerComponent(caller.getUserId());
+
+ Preconditions.checkState(poAdminComponent != null,
+ String.format("No profile owner for user %d", caller.getUid()));
+
+ ActiveAdmin poAdmin = getUserData(caller.getUserId()).mAdminMap.get(poAdminComponent);
+ Preconditions.checkState(poAdmin != null,
+ String.format("No device profile owner for caller %d", caller.getUid()));
+
+ Preconditions.checkSecurity(poAdmin.getUid() == caller.getUid(),
+ String.format("Admin %s is not owned by uid %d", poAdminComponent,
+ caller.getUid()));
+
+ Preconditions.checkSecurity(poAdmin.info.getComponent().equals(caller.getComponentName()),
+ String.format("Caller component %s is not profile owner",
+ caller.getComponentName()));
+
+ return poAdmin;
+ }
+
+ @NonNull ActiveAdmin getOrganizationOwnedProfileOwnerLocked(final CallerIdentity caller) {
+ final ActiveAdmin profileOwner = getProfileOwnerOfCallerLocked(caller);
+
+ Preconditions.checkSecurity(
+ mOwners.isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId()),
+ String.format("Admin %s is not of an org-owned device",
+ profileOwner.info.getComponent()));
+
+ return profileOwner;
+ }
+
+ @NonNull ActiveAdmin getProfileOwnerOrDeviceOwnerLocked(final CallerIdentity caller) {
+ ensureLocked();
+ // Try to find an admin which can use reqPolicy
+ final ComponentName poAdminComponent = mOwners.getProfileOwnerComponent(caller.getUserId());
+ final ComponentName doAdminComponent = mOwners.getDeviceOwnerComponent();
+
+ if (poAdminComponent == null && doAdminComponent == null) {
+ throw new IllegalStateException(
+ String.format("No profile or device owner for user %d", caller.getUid()));
+ }
+
+ if (poAdminComponent != null) {
+ return getProfileOwnerOfCallerLocked(caller);
+ }
+
+ return getDeviceOwnerOfCallerLocked(caller);
+ }
+
/**
* Finds an active admin for the caller then checks {@code permission} if admin check failed.
*
@@ -2145,9 +2228,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
ActiveAdmin result = getActiveAdminWithPolicyForUidLocked(who, reqPolicy, callingUid);
if (result != null) {
return result;
- } else if (permission != null
- && (mContext.checkCallingPermission(permission)
- == PackageManager.PERMISSION_GRANTED)) {
+ } else if (permission != null && hasCallingPermission(permission)) {
return null;
}
@@ -2844,9 +2925,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle,
Bundle onEnableData) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.MANAGE_DEVICE_ADMINS, null);
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS));
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
DevicePolicyData policy = getUserData(userHandle);
DeviceAdminInfo info = findAdmin(adminReceiver, userHandle,
@@ -2986,7 +3070,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return false;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null;
}
@@ -2997,7 +3085,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return false;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
DevicePolicyData policyData = getUserData(userHandle);
return policyData.mRemovingAdmins.contains(adminReceiver);
@@ -3009,7 +3101,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return false;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity(adminReceiver);
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (administrator == null) {
@@ -3025,8 +3121,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return Collections.EMPTY_LIST;
}
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
- enforceFullCrossUsersPermission(userHandle);
synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(userHandle);
final int N = policy.mAdminList.size();
@@ -3046,7 +3145,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return false;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(userHandle);
final int N = policy.mAdminList.size();
@@ -3156,8 +3259,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
enforceUserUnlocked(userHandle);
+
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (admin == null) {
@@ -3309,7 +3416,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return PASSWORD_QUALITY_UNSPECIFIED;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
int mode = PASSWORD_QUALITY_UNSPECIFIED;
@@ -3521,7 +3632,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return 0L;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
long timeout = 0L;
@@ -3547,12 +3662,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public boolean addCrossProfileWidgetProvider(ComponentName admin, String packageName) {
- final int userId = UserHandle.getCallingUserId();
+ final CallerIdentity identity = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isProfileOwner(identity));
List<String> changedProviders = null;
synchronized (getLockObject()) {
- ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin activeAdmin = getProfileOwnerOfCallerLocked(identity);
if (activeAdmin.crossProfileWidgetProviders == null) {
activeAdmin.crossProfileWidgetProviders = new ArrayList<>();
}
@@ -3560,7 +3675,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!providers.contains(packageName)) {
providers.add(packageName);
changedProviders = new ArrayList<>(providers);
- saveSettingsLocked(userId);
+ saveSettingsLocked(identity.getUserId());
}
}
@@ -3570,7 +3685,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.write();
if (changedProviders != null) {
- mLocalService.notifyCrossProfileProvidersChanged(userId, changedProviders);
+ mLocalService.notifyCrossProfileProvidersChanged(identity.getUserId(),
+ changedProviders);
return true;
}
@@ -3579,12 +3695,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public boolean removeCrossProfileWidgetProvider(ComponentName admin, String packageName) {
- final int userId = UserHandle.getCallingUserId();
+ final CallerIdentity identity = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isProfileOwner(identity));
List<String> changedProviders = null;
synchronized (getLockObject()) {
- ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin activeAdmin = getProfileOwnerOfCallerLocked(identity);
if (activeAdmin.crossProfileWidgetProviders == null
|| activeAdmin.crossProfileWidgetProviders.isEmpty()) {
return false;
@@ -3592,7 +3708,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
List<String> providers = activeAdmin.crossProfileWidgetProviders;
if (providers.remove(packageName)) {
changedProviders = new ArrayList<>(providers);
- saveSettingsLocked(userId);
+ saveSettingsLocked(identity.getUserId());
}
}
@@ -3602,7 +3718,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
.write();
if (changedProviders != null) {
- mLocalService.notifyCrossProfileProvidersChanged(userId, changedProviders);
+ mLocalService.notifyCrossProfileProvidersChanged(identity.getUserId(),
+ changedProviders);
return true;
}
@@ -3611,9 +3728,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public List<String> getCrossProfileWidgetProviders(ComponentName admin) {
+ final CallerIdentity identity = getCallerIdentity(admin);
+ Preconditions.checkCallAuthorization(isProfileOwner(identity));
+
synchronized (getLockObject()) {
- ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin activeAdmin = getProfileOwnerOfCallerLocked(identity);
if (activeAdmin.crossProfileWidgetProviders == null
|| activeAdmin.crossProfileWidgetProviders.isEmpty()) {
return null;
@@ -3656,7 +3775,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return 0L;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
return getPasswordExpirationLocked(who, userHandle, parent);
}
@@ -3862,7 +3985,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return 0;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
if (who != null) {
final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent);
@@ -3902,7 +4029,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
new PasswordMetrics(CREDENTIAL_TYPE_NONE);
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
ArrayList<PasswordMetrics> adminMetrics = new ArrayList<>();
synchronized (getLockObject()) {
List<ActiveAdmin> admins =
@@ -3919,7 +4050,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return true;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
enforceUserUnlocked(userHandle, parent);
synchronized (getLockObject()) {
@@ -3951,7 +4085,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return true;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
enforceManagedProfile(userHandle, "call APIs refering to the parent profile");
synchronized (getLockObject()) {
@@ -3970,7 +4107,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return true;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
enforceNotManagedProfile(userHandle, "check password sufficiency");
enforceUserUnlocked(userHandle);
@@ -4058,12 +4198,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mLockPatternUtils.hasSecureLockScreen()) {
return 0;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
- if (!isCallerWithSystemUid()) {
+ if (!isSystemUid(identity)) {
// This API can be called by an active device admin or by keyguard code.
- if (mContext.checkCallingPermission(permission.ACCESS_KEYGUARD_SECURE_STORAGE)
- != PackageManager.PERMISSION_GRANTED) {
+ if (!hasCallingPermission(permission.ACCESS_KEYGUARD_SECURE_STORAGE)) {
getActiveAdminForCallerLocked(
null, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent);
}
@@ -4106,7 +4249,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return 0;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
ActiveAdmin admin = (who != null)
? getActiveAdminUncheckedLocked(who, userHandle, parent)
@@ -4120,7 +4267,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature || !mLockPatternUtils.hasSecureLockScreen()) {
return UserHandle.USER_NULL;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
ActiveAdmin admin = getAdminWithMinimumFailedPasswordsForWipeLocked(
userHandle, parent);
@@ -4191,8 +4342,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// As of R, only privlleged caller holding RESET_PASSWORD can call resetPassword() to
// set password to an unsecured user.
- if (mContext.checkCallingPermission(permission.RESET_PASSWORD)
- == PackageManager.PERMISSION_GRANTED) {
+ if (hasCallingPermission(permission.RESET_PASSWORD)) {
return setPasswordPrivileged(password, flags, callingUid);
}
@@ -4392,7 +4542,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return 0;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
if (who != null) {
final ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent);
@@ -4465,12 +4619,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS;
}
+ Preconditions.checkArgumentNonnegative(userId, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userId));
+
if (!mLockPatternUtils.hasSecureLockScreen()) {
// No strong auth timeout on devices not supporting the
// {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature
return 0;
}
- enforceFullCrossUsersPermission(userId);
synchronized (getLockObject()) {
if (who != null) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userId, parent);
@@ -4504,8 +4662,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void lockNow(int flags, boolean parent) {
- if (!mHasFeature && mContext.checkCallingPermission(android.Manifest.permission.LOCK_DEVICE)
- != PackageManager.PERMISSION_GRANTED) {
+ if (!mHasFeature && !hasCallingPermission(permission.LOCK_DEVICE)) {
return;
}
@@ -4597,8 +4754,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private void enforceNetworkStackOrProfileOrDeviceOwner(ComponentName who) {
- if (mContext.checkCallingPermission(PERMISSION_MAINLINE_NETWORK_STACK)
- == PackageManager.PERMISSION_GRANTED) {
+ if (hasCallingPermission(PERMISSION_MAINLINE_NETWORK_STACK)) {
return;
}
enforceProfileOrDeviceOwner(who);
@@ -5677,8 +5833,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return;
}
-
- enforceFullCrossUsersPermission(mInjector.userHandleGetCallingUserId());
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(isSystemUid(identity) || isRootUid(identity)
+ || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS_FULL));
final ActiveAdmin admin;
synchronized (getLockObject()) {
@@ -5854,8 +6011,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
synchronized (getLockObject()) {
if (who == null) {
if ((frpManagementAgentUid != mInjector.binderGetCallingUid())
- && (mContext.checkCallingPermission(permission.MASTER_CLEAR)
- != PackageManager.PERMISSION_GRANTED)) {
+ && !hasCallingPermission(permission.MASTER_CLEAR)) {
throw new SecurityException(
"Must be called by the FRP management agent on device");
}
@@ -5893,9 +6049,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return;
}
- enforceFullCrossUsersPermission(userHandle);
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = comp != null
+ ? getCallerIdentity(comp)
+ : getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+ Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN));
synchronized (getLockObject()) {
ActiveAdmin admin = getActiveAdminUncheckedLocked(comp, userHandle);
@@ -5972,13 +6132,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void reportFailedPasswordAttempt(int userHandle) {
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+ Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN));
if (!isSeparateProfileChallengeEnabled(userHandle)) {
enforceNotManagedProfile(userHandle,
"report failed password attempt if separate profile challenge is not in place");
}
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.BIND_DEVICE_ADMIN, null);
boolean wipeData = false;
ActiveAdmin strictestAdmin = null;
@@ -6051,9 +6213,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void reportSuccessfulPasswordAttempt(int userHandle) {
- enforceFullCrossUsersPermission(userHandle);
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+ Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN));
synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(userHandle);
@@ -6079,9 +6243,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void reportFailedBiometricAttempt(int userHandle) {
- enforceFullCrossUsersPermission(userHandle);
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+ Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN));
+
if (mInjector.securityLogIsLoggingEnabled()) {
SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT, /*result*/ 0,
/*method strength*/ 0);
@@ -6090,9 +6257,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void reportSuccessfulBiometricAttempt(int userHandle) {
- enforceFullCrossUsersPermission(userHandle);
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+ Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN));
+
if (mInjector.securityLogIsLoggingEnabled()) {
SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT, /*result*/ 1,
/*method strength*/ 0);
@@ -6101,9 +6271,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void reportKeyguardDismissed(int userHandle) {
- enforceFullCrossUsersPermission(userHandle);
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+ Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN));
if (mInjector.securityLogIsLoggingEnabled()) {
SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_DISMISSED);
@@ -6112,9 +6284,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void reportKeyguardSecured(int userHandle) {
- enforceFullCrossUsersPermission(userHandle);
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.BIND_DEVICE_ADMIN, null);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+ Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN));
if (mInjector.securityLogIsLoggingEnabled()) {
SecurityLog.writeEvent(SecurityLog.TAG_KEYGUARD_SECURED);
@@ -6176,7 +6350,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return null;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
// Scan through active admins and find if anyone has already
@@ -6310,7 +6488,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return false;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = who != null
+ ? getCallerIdentity(who)
+ : getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
// Check for permissions if a particular caller is specified
if (who != null) {
@@ -6340,7 +6524,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
// Ok to return current status.
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = callerPackage != null
+ ? getCallerIdentity(callerPackage)
+ : getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
// It's not critical here, but let's make sure the package name is correct, in case
// we start using it for different purposes.
@@ -6485,24 +6674,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return;
}
Objects.requireNonNull(who, "ComponentName is null");
- final int userHandle = UserHandle.getCallingUserId();
+ final CallerIdentity identity = getCallerIdentity(who);
+
boolean requireAutoTimeChanged = false;
synchronized (getLockObject()) {
- if (isManagedProfile(userHandle)) {
- throw new SecurityException("Managed profile cannot set auto time required");
- }
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ Preconditions.checkSecurity(!isManagedProfile(identity.getUserId()),
+ "Managed profile cannot set auto time required");
+ ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
if (admin.requireAutoTime != required) {
admin.requireAutoTime = required;
- saveSettingsLocked(userHandle);
+ saveSettingsLocked(identity.getUserId());
requireAutoTimeChanged = true;
}
}
// requireAutoTime is now backed by DISALLOW_CONFIG_DATE_TIME restriction, so propagate
// updated restrictions to the framework.
if (requireAutoTimeChanged) {
- pushUserRestrictions(userHandle);
+ pushUserRestrictions(identity.getUserId());
}
// Turn AUTO_TIME on in settings if it is required
if (required) {
@@ -7033,7 +7221,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return 0;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
final long ident = mInjector.binderClearCallingIdentity();
try {
synchronized (getLockObject()) {
@@ -7229,6 +7421,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return who != null && who.equals(profileOwner);
}
+ /**
+ * Returns {@code true} if the provided caller identity is of a profile owner.
+ * @param identity identity of caller.
+ * @return true if {@code identity} is a profile owner, false otherwise.
+ */
+ public boolean isProfileOwner(CallerIdentity identity) {
+ final ComponentName profileOwner = getProfileOwner(identity.getUserId());
+ return profileOwner != null && profileOwner.equals(identity.getComponentName());
+ }
+
private boolean hasProfileOwner(int userId) {
synchronized (getLockObject()) {
return mOwners.hasProfileOwner(userId);
@@ -7783,7 +7985,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public ComponentName getProfileOwnerAsUser(int userHandle) {
- enforceCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasCrossUsersPermission(identity, userHandle));
return getProfileOwner(userHandle);
}
@@ -8140,56 +8345,31 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
- private void enforceAcrossUsersPermissions() {
- final int callingUid = mInjector.binderGetCallingUid();
- final int callingPid = mInjector.binderGetCallingPid();
- final String packageName = mContext.getPackageName();
-
- if (isCallerWithSystemUid() || callingUid == Process.ROOT_UID) {
- return;
- }
- if (PermissionChecker.checkPermissionForPreflight(
- mContext, permission.INTERACT_ACROSS_PROFILES, callingPid, callingUid,
- packageName) == PermissionChecker.PERMISSION_GRANTED) {
- return;
- }
- if (mContext.checkCallingPermission(permission.INTERACT_ACROSS_USERS)
- == PackageManager.PERMISSION_GRANTED) {
- return;
- }
- if (mContext.checkCallingPermission(permission.INTERACT_ACROSS_USERS_FULL)
- == PackageManager.PERMISSION_GRANTED) {
- return;
- }
- throw new SecurityException("Calling user does not have INTERACT_ACROSS_PROFILES or"
- + "INTERACT_ACROSS_USERS or INTERACT_ACROSS_USERS_FULL permissions");
+ private boolean hasCallingPermission(String permission) {
+ return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED;
}
- private void enforceFullCrossUsersPermission(int userHandle) {
- enforceSystemUserOrPermissionIfCrossUser(userHandle,
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+ private boolean hasCallingOrSelfPermission(String permission) {
+ return mContext.checkCallingOrSelfPermission(permission)
+ == PackageManager.PERMISSION_GRANTED;
}
- private void enforceCrossUsersPermission(int userHandle) {
- enforceSystemUserOrPermissionIfCrossUser(userHandle,
- android.Manifest.permission.INTERACT_ACROSS_USERS);
+ private boolean hasPermissionForPreflight(CallerIdentity identity, String permission) {
+ final int callingPid = mInjector.binderGetCallingPid();
+ final String packageName = mContext.getPackageName();
+
+ return PermissionChecker.checkPermissionForPreflight(mContext, permission, callingPid,
+ identity.getUid(), packageName) == PermissionChecker.PERMISSION_GRANTED;
}
- private void enforceSystemUserOrPermission(String permission) {
- if (!(isCallerWithSystemUid() || mInjector.binderGetCallingUid() == Process.ROOT_UID)) {
- mContext.enforceCallingOrSelfPermission(permission,
- "Must be system or have " + permission + " permission");
- }
+ private boolean hasFullCrossUsersPermission(CallerIdentity identity, int userHandle) {
+ return (userHandle == identity.getUserId()) || isSystemUid(identity) || isRootUid(identity)
+ || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS_FULL);
}
- private void enforceSystemUserOrPermissionIfCrossUser(int userHandle, String permission) {
- if (userHandle < 0) {
- throw new IllegalArgumentException("Invalid userId " + userHandle);
- }
- if (userHandle == mInjector.userHandleGetCallingUserId()) {
- return;
- }
- enforceSystemUserOrPermission(permission);
+ private boolean hasCrossUsersPermission(CallerIdentity identity, int userHandle) {
+ return (userHandle == identity.getUserId()) || isSystemUid(identity) || isRootUid(identity)
+ || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS);
}
private void enforceManagedProfile(int userId, String message) {
@@ -8249,19 +8429,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
throw new SecurityException("No active admin found");
}
- private void enforceProfileOwnerOrFullCrossUsersPermission(int userId) {
- if (userId == mInjector.userHandleGetCallingUserId()) {
+ private void enforceProfileOwnerOrFullCrossUsersPermission(CallerIdentity identity,
+ int userId) {
+ if (userId == identity.getUserId()) {
synchronized (getLockObject()) {
if (getActiveAdminWithPolicyForUidLocked(null,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, mInjector.binderGetCallingUid())
- != null) {
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, identity.getUid()) != null) {
// Device Owner/Profile Owner may access the user it runs on.
return;
}
}
}
- // Otherwise, INTERACT_ACROSS_USERS_FULL permission, system UID or root UID is required.
- enforceSystemUserOrPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userId));
}
private boolean canUserUseLockTaskLocked(int userId) {
@@ -8315,6 +8494,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID);
}
+ private boolean isSystemUid(CallerIdentity identity) {
+ return UserHandle.isSameApp(identity.getUid(), Process.SYSTEM_UID);
+ }
+
+ private boolean isRootUid(CallerIdentity identity) {
+ return UserHandle.isSameApp(identity.getUid(), Process.ROOT_UID);
+ }
+
+ private boolean isShellUid(CallerIdentity identity) {
+ return UserHandle.isSameApp(identity.getUid(), Process.SHELL_UID);
+ }
+
protected int getProfileParentId(int userHandle) {
return mInjector.binderWithCleanCallingIdentity(() -> {
UserInfo parentUser = mUserManager.getProfileParent(userHandle);
@@ -8569,7 +8760,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return null;
}
Objects.requireNonNull(agent, "agent null");
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = admin != null
+ ? getCallerIdentity(admin)
+ : getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
synchronized (getLockObject()) {
final String componentName = agent.flattenToString();
@@ -8769,9 +8965,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
if (packageList != null) {
- int userId = UserHandle.getCallingUserId();
+ int userId = identity.getUserId();
List<AccessibilityServiceInfo> enabledServices = null;
long id = mInjector.binderClearCallingIdentity();
try {
@@ -8801,8 +8998,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
admin.permittedAccessiblityServices = packageList;
saveSettingsLocked(UserHandle.getCallingUserId());
}
@@ -8822,10 +9018,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return null;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isDeviceOwner(identity) || isProfileOwner(identity));
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
return admin.permittedAccessiblityServices;
}
}
@@ -8920,17 +9117,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
Objects.requireNonNull(who, "ComponentName is null");
- final int callingUserId = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity identity = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isDeviceOwner(identity) || isProfileOwner(identity));
+
if (packageList != null) {
List<InputMethodInfo> enabledImes = InputMethodManagerInternal.get()
- .getEnabledInputMethodListAsUser(callingUserId);
+ .getEnabledInputMethodListAsUser(identity.getUserId());
if (enabledImes != null) {
List<String> enabledPackages = new ArrayList<String>();
for (InputMethodInfo ime : enabledImes) {
enabledPackages.add(ime.getPackageName());
}
if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList,
- callingUserId)) {
+ identity.getUserId())) {
Slog.e(LOG_TAG, "Cannot set permitted input methods, "
+ "because it contains already enabled input method.");
return false;
@@ -8939,10 +9138,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
admin.permittedInputMethods = packageList;
- saveSettingsLocked(callingUserId);
+ saveSettingsLocked(identity.getUserId());
}
final String[] packageArray =
packageList != null ? ((List<String>) packageList).toArray(new String[0]) : null;
@@ -8960,10 +9158,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return null;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isDeviceOwner(identity) || isProfileOwner(identity));
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
return admin.permittedInputMethods;
}
}
@@ -9037,17 +9236,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
- final int callingUserId = mInjector.userHandleGetCallingUserId();
- if (!isManagedProfile(callingUserId)) {
+ if (!isManagedProfile(identity.getUserId())) {
return false;
}
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(
- who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity);
admin.permittedNotificationListeners = packageList;
- saveSettingsLocked(callingUserId);
+ saveSettingsLocked(identity.getUserId());
}
return true;
}
@@ -9058,10 +9256,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return null;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(
- who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ // API contract is to return null if there are no permitted cross-profile notification
+ // listeners, including in Device Owner mode.
+ ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
return admin.permittedNotificationListeners;
}
}
@@ -9922,10 +10122,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public String[] getAccountTypesWithManagementDisabledAsUser(int userId, boolean parent) {
- enforceFullCrossUsersPermission(userId);
if (!mHasFeature) {
return null;
}
+ Preconditions.checkArgumentNonnegative(userId, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userId));
+
synchronized (getLockObject()) {
final ArraySet<String> resultSet = new ArraySet<>();
@@ -9992,10 +10196,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final int userId = UserHandle.getCallingUserId();
synchronized (getLockObject()) {
+ //TODO: This is a silly access control check. Remove.
if (who != null) {
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final CallerIdentity caller = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDeviceOwner(caller));
}
-
long id = mInjector.binderClearCallingIdentity();
try {
return mIPackageManager.getBlockUninstallForUser(packageName, userId);
@@ -10015,12 +10221,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(identity));
+
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity);
if (admin.disableCallerId != disabled) {
admin.disableCallerId = disabled;
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ saveSettingsLocked(identity.getUserId());
}
}
DevicePolicyEventLogger
@@ -10036,16 +10244,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(identity));
+
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity);
return admin.disableCallerId;
}
}
@Override
public boolean getCrossProfileCallerIdDisabledForUser(int userId) {
- enforceCrossUsersPermission(userId);
+ Preconditions.checkArgumentNonnegative(userId, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasCrossUsersPermission(identity, userId));
+
synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerAdminLocked(userId);
return (admin != null) ? admin.disableCallerId : false;
@@ -10058,12 +10272,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(identity));
+
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity);
if (admin.disableContactsSearch != disabled) {
admin.disableContactsSearch = disabled;
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ saveSettingsLocked(identity.getUserId());
}
}
DevicePolicyEventLogger
@@ -10079,16 +10295,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isProfileOwner(identity));
+
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity);
return admin.disableContactsSearch;
}
}
@Override
public boolean getCrossProfileContactsSearchDisabledForUser(int userId) {
- enforceCrossUsersPermission(userId);
+ Preconditions.checkArgumentNonnegative(userId, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasCrossUsersPermission(identity, userId));
+
synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerAdminLocked(userId);
return (admin != null) ? admin.disableContactsSearch : false;
@@ -10159,12 +10381,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isDeviceOwner(identity) || isProfileOwner(identity));
+
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
if (admin.disableBluetoothContactSharing != disabled) {
admin.disableBluetoothContactSharing = disabled;
- saveSettingsLocked(UserHandle.getCallingUserId());
+ saveSettingsLocked(identity.getUserId());
}
}
DevicePolicyEventLogger
@@ -10180,9 +10404,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
+ Preconditions.checkCallAuthorization(isDeviceOwner(identity) || isProfileOwner(identity));
+
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
return admin.disableBluetoothContactSharing;
}
}
@@ -12138,13 +12364,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return;
}
Objects.requireNonNull(who, "ComponentName is null");
- final int userHandle = mInjector.userHandleGetCallingUserId();
- enforceManagedProfile(userHandle, "set organization color");
+ final CallerIdentity identity = getCallerIdentity(who);
+ enforceManagedProfile(identity.getUserId(), "set organization color");
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
admin.organizationColor = color;
- saveSettingsLocked(userHandle);
+ saveSettingsLocked(identity.getUserId());
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_ORGANIZATION_COLOR)
@@ -12157,7 +12382,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return;
}
- enforceFullCrossUsersPermission(userId);
+ Preconditions.checkArgumentNonnegative(userId, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userId));
+
enforceManageUsers();
enforceManagedProfile(userId, "set organization color");
synchronized (getLockObject()) {
@@ -12173,10 +12402,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return ActiveAdmin.DEF_ORGANIZATION_COLOR;
}
Objects.requireNonNull(who, "ComponentName is null");
- enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization color");
+ final CallerIdentity identity = getCallerIdentity(who);
+ enforceManagedProfile(identity.getUserId(), "get organization color");
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
return admin.organizationColor;
}
}
@@ -12186,7 +12415,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return ActiveAdmin.DEF_ORGANIZATION_COLOR;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
enforceManagedProfile(userHandle, "get organization color");
synchronized (getLockObject()) {
ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle);
@@ -12202,15 +12435,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return;
}
Objects.requireNonNull(who, "ComponentName is null");
- final int userHandle = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity identity = getCallerIdentity(who);
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
if (!TextUtils.equals(admin.organizationName, text)) {
admin.organizationName = (text == null || text.length() == 0)
? null : text.toString();
- saveSettingsLocked(userHandle);
+ saveSettingsLocked(identity.getUserId());
}
}
}
@@ -12221,10 +12453,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return null;
}
Objects.requireNonNull(who, "ComponentName is null");
- enforceManagedProfile(mInjector.userHandleGetCallingUserId(), "get organization name");
+ final CallerIdentity identity = getCallerIdentity(who);
+ enforceManagedProfile(identity.getUserId(), "get organization name");
synchronized (getLockObject()) {
- ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
return admin.organizationName;
}
}
@@ -12246,7 +12478,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return null;
}
- enforceFullCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(identity, userHandle));
+
enforceManagedProfile(userHandle, "get organization name");
synchronized (getLockObject()) {
ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userHandle);
@@ -12260,20 +12496,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public List<String> setMeteredDataDisabledPackages(ComponentName who, List<String> packageNames) {
Objects.requireNonNull(who);
Objects.requireNonNull(packageNames);
+ final CallerIdentity identity = getCallerIdentity(who);
+ Preconditions.checkSecurity(isDeviceOwner(identity) || isProfileOwner(identity),
+ String.format("Admin %s does not own the profile", identity.getComponentName()));
if (!mHasFeature) {
return packageNames;
}
synchronized (getLockObject()) {
- final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- final int callingUserId = mInjector.userHandleGetCallingUserId();
+ final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
return mInjector.binderWithCleanCallingIdentity(() -> {
- final List<String> excludedPkgs
- = removeInvalidPkgsForMeteredDataRestriction(callingUserId, packageNames);
+ final List<String> excludedPkgs = removeInvalidPkgsForMeteredDataRestriction(
+ identity.getUserId(), packageNames);
admin.meteredDisabledPackages = packageNames;
- pushMeteredDisabledPackagesLocked(callingUserId);
- saveSettingsLocked(callingUserId);
+ pushMeteredDisabledPackagesLocked(identity.getUserId());
+ saveSettingsLocked(identity.getUserId());
return excludedPkgs;
});
}
@@ -12310,9 +12547,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return new ArrayList<>();
}
+ final CallerIdentity identity = getCallerIdentity(who);
+ Preconditions.checkSecurity(isDeviceOwner(identity) || isProfileOwner(identity),
+ String.format("Admin %s does not own the profile", identity.getComponentName()));
+
synchronized (getLockObject()) {
- final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(identity);
return admin.meteredDisabledPackages == null
? new ArrayList<>() : admin.meteredDisabledPackages;
}
@@ -12337,12 +12577,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
- private boolean hasMarkProfileOwnerOnOrganizationOwnedDevicePermission() {
- return mContext.checkCallingPermission(
- permission.MARK_DEVICE_ORGANIZATION_OWNED)
- == PackageManager.PERMISSION_GRANTED;
- }
-
@Override
public void markProfileOwnerOnOrganizationOwnedDevice(ComponentName who, int userId) {
// As the caller is the system, it must specify the component name of the profile owner
@@ -12355,7 +12589,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Only adb or system apps with the right permission can mark a profile owner on
// organization-owned device.
- if (!(isAdb() || hasMarkProfileOwnerOnOrganizationOwnedDevicePermission())) {
+ if (!(isAdb() || hasCallingPermission(permission.MARK_DEVICE_ORGANIZATION_OWNED))) {
throw new SecurityException(
"Only the system can mark a profile owner of organization-owned device.");
}
@@ -13483,7 +13717,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public StringParceledListSlice getOwnerInstalledCaCerts(@NonNull UserHandle user) {
final int userId = user.getIdentifier();
- enforceProfileOwnerOrFullCrossUsersPermission(userId);
+ final CallerIdentity identity = getCallerIdentity();
+ enforceProfileOwnerOrFullCrossUsersPermission(identity, userId);
synchronized (getLockObject()) {
return new StringParceledListSlice(
new ArrayList<>(getUserData(userId).mOwnerInstalledCaCerts));
@@ -14100,12 +14335,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return;
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
synchronized (getLockObject()) {
- final ActiveAdmin admin = getActiveAdminForCallerLocked(
- who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity);
admin.mCrossProfileCalendarPackages = packageNames;
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ saveSettingsLocked(identity.getUserId());
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_CROSS_PROFILE_CALENDAR_PACKAGES)
@@ -14121,10 +14356,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return Collections.emptyList();
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
synchronized (getLockObject()) {
- final ActiveAdmin admin = getActiveAdminForCallerLocked(
- who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity);
return admin.mCrossProfileCalendarPackages;
}
}
@@ -14136,8 +14371,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
Preconditions.checkStringNotEmpty(packageName, "Package name is null or empty");
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasCrossUsersPermission(identity, userHandle));
- enforceCrossUsersPermission(userHandle);
synchronized (getLockObject()) {
if (mInjector.settingsSecureGetIntForUser(
Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED, 0, userHandle) == 0) {
@@ -14159,7 +14397,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return Collections.emptyList();
}
- enforceCrossUsersPermission(userHandle);
+ Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
+
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(hasCrossUsersPermission(identity, userHandle));
+
synchronized (getLockObject()) {
final ActiveAdmin admin = getProfileOwnerAdminLocked(userHandle);
if (admin != null) {
@@ -14176,16 +14418,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(who, "ComponentName is null");
Objects.requireNonNull(packageNames, "Package names is null");
+ final CallerIdentity identity = getCallerIdentity(who);
+
final List<String> previousCrossProfilePackages;
synchronized (getLockObject()) {
- final ActiveAdmin admin =
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity);
previousCrossProfilePackages = admin.mCrossProfilePackages;
if (packageNames.equals(previousCrossProfilePackages)) {
return;
}
admin.mCrossProfilePackages = packageNames;
- saveSettingsLocked(mInjector.userHandleGetCallingUserId());
+ saveSettingsLocked(identity.getUserId());
}
logSetCrossProfilePackages(who, packageNames);
final CrossProfileApps crossProfileApps = mContext.getSystemService(CrossProfileApps.class);
@@ -14208,10 +14451,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return Collections.emptyList();
}
Objects.requireNonNull(who, "ComponentName is null");
+ final CallerIdentity identity = getCallerIdentity(who);
synchronized (getLockObject()) {
- final ActiveAdmin admin = getActiveAdminForCallerLocked(
- who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final ActiveAdmin admin = getProfileOwnerOfCallerLocked(identity);
return admin.mCrossProfilePackages;
}
}
@@ -14221,7 +14464,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return Collections.emptyList();
}
- enforceAcrossUsersPermissions();
+ final CallerIdentity identity = getCallerIdentity();
+ Preconditions.checkCallAuthorization(
+ isSystemUid(identity) || isRootUid(identity) || hasCallingPermission(
+ permission.INTERACT_ACROSS_USERS) || hasCallingPermission(
+ permission.INTERACT_ACROSS_USERS_FULL) || hasPermissionForPreflight(
+ identity, permission.INTERACT_ACROSS_PROFILES));
synchronized (getLockObject()) {
final List<ActiveAdmin> admins = getProfileOwnerAdminsForCurrentProfileGroup();
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 32afe8244eb6..e6fc792c6a9d 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -4465,6 +4465,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 19436);
addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
+ mServiceContext.permissions.add(permission.INTERACT_ACROSS_USERS_FULL);
// Even if the caller is the managed profile, the current user is the user 0
when(getServices().iactivityManager.getCurrentUser())
@@ -5694,6 +5695,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
final long ident = mServiceContext.binder.clearCallingIdentity();
configureContextForAccess(mServiceContext, true);
+ mServiceContext.permissions.add(permission.MARK_DEVICE_ORGANIZATION_OWNED);
mServiceContext.binder.callingUid =
UserHandle.getUid(CALLER_USER_HANDLE,
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index ce7ac9e796d2..09b6d7b0cd7e 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -259,18 +259,7 @@ public class DpmMockContext extends MockContext {
@Override
public int checkPermission(String permission, int pid, int uid) {
- if (UserHandle.isSameApp(binder.getCallingUid(), SYSTEM_UID)) {
- return PackageManager.PERMISSION_GRANTED; // Assume system has all permissions.
- }
- List<String> permissions = binder.callingPermissions.get(binder.getCallingUid());
- if (permissions == null) {
- permissions = callerPermissions;
- }
- if (permissions.contains(permission)) {
- return PackageManager.PERMISSION_GRANTED;
- } else {
- return PackageManager.PERMISSION_DENIED;
- }
+ return checkPermission(permission);
}
@Override
@@ -480,11 +469,32 @@ public class DpmMockContext extends MockContext {
@Override
public int checkCallingPermission(String permission) {
- return spiedContext.checkCallingPermission(permission);
+ return checkPermission(permission);
+ }
+
+ @Override
+ public int checkCallingOrSelfPermission(String permission) {
+ return checkPermission(permission);
}
@Override
public void startActivityAsUser(Intent intent, UserHandle userHandle) {
spiedContext.startActivityAsUser(intent, userHandle);
}
+
+ private int checkPermission(String permission) {
+ if (UserHandle.isSameApp(binder.getCallingUid(), SYSTEM_UID)) {
+ return PackageManager.PERMISSION_GRANTED; // Assume system has all permissions.
+ }
+ List<String> permissions = binder.callingPermissions.get(binder.getCallingUid());
+ if (permissions == null) {
+ permissions = callerPermissions;
+ }
+ if (permissions.contains(permission)) {
+ return PackageManager.PERMISSION_GRANTED;
+ } else {
+ return PackageManager.PERMISSION_DENIED;
+ }
+ }
+
}
diff --git a/services/tests/servicestests/src/com/android/server/job/MaxJobCountsTest.java b/services/tests/servicestests/src/com/android/server/job/MaxJobCountsTest.java
index 0219f2201675..4c3674767e97 100644
--- a/services/tests/servicestests/src/com/android/server/job/MaxJobCountsTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/MaxJobCountsTest.java
@@ -15,13 +15,15 @@
*/
package com.android.server.job;
-import android.util.KeyValueListParser;
+import android.annotation.Nullable;
+import android.provider.DeviceConfig;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.job.JobSchedulerService.MaxJobCounts;
+import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -29,19 +31,32 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class MaxJobCountsTest {
+ @After
+ public void tearDown() throws Exception {
+ resetConfig();
+ }
+
+ private void resetConfig() {
+ // DeviceConfig.resetToDefaults() doesn't work here. Need to reset constants manually.
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, "total", "", false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, "maxbg", "", false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, "minbg", "", false);
+ }
- private void check(String config,
+ private void check(@Nullable DeviceConfig.Properties config,
int defaultTotal, int defaultMaxBg, int defaultMinBg,
- int expectedTotal, int expectedMaxBg, int expectedMinBg) {
- final KeyValueListParser parser = new KeyValueListParser(',');
- parser.setString(config);
+ int expectedTotal, int expectedMaxBg, int expectedMinBg) throws Exception {
+ resetConfig();
+ if (config != null) {
+ DeviceConfig.setProperties(config);
+ }
final MaxJobCounts counts = new JobSchedulerService.MaxJobCounts(
defaultTotal, "total",
defaultMaxBg, "maxbg",
defaultMinBg, "minbg");
- counts.parse(parser);
+ counts.update();
Assert.assertEquals(expectedTotal, counts.getMaxTotal());
Assert.assertEquals(expectedMaxBg, counts.getMaxBg());
@@ -49,24 +64,35 @@ public class MaxJobCountsTest {
}
@Test
- public void test() {
+ public void test() throws Exception {
// Tests with various combinations.
- check("", /*default*/ 5, 1, 0, /*expected*/ 5, 1, 0);
- check("", /*default*/ 5, 0, 0, /*expected*/ 5, 1, 0);
- check("", /*default*/ 0, 0, 0, /*expected*/ 1, 1, 0);
- check("", /*default*/ -1, -1, -1, /*expected*/ 1, 1, 0);
- check("", /*default*/ 5, 5, 5, /*expected*/ 5, 5, 4);
- check("", /*default*/ 6, 5, 6, /*expected*/ 6, 5, 5);
- check("", /*default*/ 4, 5, 6, /*expected*/ 4, 4, 3);
- check("", /*default*/ 5, 1, 1, /*expected*/ 5, 1, 1);
- check("", /*default*/ 15, 15, 15, /*expected*/ 15, 15, 14);
- check("", /*default*/ 16, 16, 16, /*expected*/ 16, 16, 15);
- check("", /*default*/ 20, 20, 20, /*expected*/ 16, 16, 15);
+ check(null, /*default*/ 5, 1, 0, /*expected*/ 5, 1, 0);
+ check(null, /*default*/ 5, 0, 0, /*expected*/ 5, 1, 0);
+ check(null, /*default*/ 0, 0, 0, /*expected*/ 1, 1, 0);
+ check(null, /*default*/ -1, -1, -1, /*expected*/ 1, 1, 0);
+ check(null, /*default*/ 5, 5, 5, /*expected*/ 5, 5, 4);
+ check(null, /*default*/ 6, 5, 6, /*expected*/ 6, 5, 5);
+ check(null, /*default*/ 4, 5, 6, /*expected*/ 4, 4, 3);
+ check(null, /*default*/ 5, 1, 1, /*expected*/ 5, 1, 1);
+ check(null, /*default*/ 15, 15, 15, /*expected*/ 15, 15, 14);
+ check(null, /*default*/ 16, 16, 16, /*expected*/ 16, 16, 15);
+ check(null, /*default*/ 20, 20, 20, /*expected*/ 16, 16, 15);
// Test for overriding with a setting string.
- check("total=5,maxbg=4,minbg=3", /*default*/ 9, 9, 9, /*expected*/ 5, 4, 3);
- check("total=5", /*default*/ 9, 9, 9, /*expected*/ 5, 5, 4);
- check("maxbg=4", /*default*/ 9, 9, 9, /*expected*/ 9, 4, 4);
- check("minbg=3", /*default*/ 9, 9, 9, /*expected*/ 9, 9, 3);
+ check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
+ .setInt("total", 5)
+ .setInt("maxbg", 4)
+ .setInt("minbg", 3)
+ .build(),
+ /*default*/ 9, 9, 9, /*expected*/ 5, 4, 3);
+ check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
+ .setInt("total", 5).build(),
+ /*default*/ 9, 9, 9, /*expected*/ 5, 5, 4);
+ check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
+ .setInt("maxbg", 4).build(),
+ /*default*/ 9, 9, 9, /*expected*/ 9, 4, 4);
+ check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
+ .setInt("minbg", 3).build(),
+ /*default*/ 9, 9, 9, /*expected*/ 9, 9, 3);
}
}
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index 06c34dcf290a..905f90800305 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -50,6 +50,18 @@ public final class CellIdentityNr extends CellIdentity {
// a list of additional PLMN-IDs reported for this cell
private final ArraySet<String> mAdditionalPlmns;
+ /** @hide */
+ public CellIdentityNr() {
+ super(TAG, CellInfo.TYPE_NR, null, null, null, null);
+ mNrArfcn = CellInfo.UNAVAILABLE;
+ mPci = CellInfo.UNAVAILABLE;
+ mTac = CellInfo.UNAVAILABLE;
+ mNci = CellInfo.UNAVAILABLE;
+ mBands = new int[] {};
+ mAdditionalPlmns = new ArraySet();
+ mGlobalCellId = null;
+ }
+
/**
*
* @param pci Physical Cell Id in range [0, 1007].
diff --git a/telephony/java/android/telephony/CellInfoNr.java b/telephony/java/android/telephony/CellInfoNr.java
index a7e79f93ae89..e01e8f0d5b51 100644
--- a/telephony/java/android/telephony/CellInfoNr.java
+++ b/telephony/java/android/telephony/CellInfoNr.java
@@ -29,9 +29,16 @@ import java.util.Objects;
public final class CellInfoNr extends CellInfo {
private static final String TAG = "CellInfoNr";
- private final CellIdentityNr mCellIdentity;
+ private CellIdentityNr mCellIdentity;
private final CellSignalStrengthNr mCellSignalStrength;
+ /** @hide */
+ public CellInfoNr() {
+ super();
+ mCellIdentity = new CellIdentityNr();
+ mCellSignalStrength = new CellSignalStrengthNr();
+ }
+
private CellInfoNr(Parcel in) {
super(in);
mCellIdentity = CellIdentityNr.CREATOR.createFromParcel(in);
@@ -71,6 +78,11 @@ public final class CellInfoNr extends CellInfo {
return mCellIdentity;
}
+ /** @hide */
+ public void setCellIdentity(CellIdentityNr cid) {
+ mCellIdentity = cid;
+ }
+
/**
* @return a {@link CellSignalStrengthNr} instance.
*/