Merge "Add a SetSchema API and builders."
diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp
index c9d9d6c..69a9fd8 100644
--- a/apex/jobscheduler/service/Android.bp
+++ b/apex/jobscheduler/service/Android.bp
@@ -9,6 +9,7 @@
],
libs: [
+ "app-compat-annotations",
"framework",
"services.core",
],
diff --git a/apex/jobscheduler/service/java/com/android/server/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/TEST_MAPPING
new file mode 100644
index 0000000..8fbfb1d
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/TEST_MAPPING
@@ -0,0 +1,22 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksMockingServicesTests",
+ "file_patterns": [
+ "DeviceIdleController\\.java"
+ ],
+ "options": [
+ {"include-filter": "com.android.server.DeviceIdleControllerTest"},
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"}
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "FrameworksMockingServicesTests",
+ "options": [
+ {"include-filter": "com.android.server"}
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/apex/jobscheduler/service/java/com/android/server/deviceidle/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/deviceidle/TEST_MAPPING
new file mode 100644
index 0000000..bc7a7d3
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/deviceidle/TEST_MAPPING
@@ -0,0 +1,19 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksMockingServicesTests",
+ "options": [
+ {"include-filter": "com.android.server.DeviceIdleControllerTest"},
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"}
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "FrameworksMockingServicesTests",
+ "options": [
+ {"include-filter": "com.android.server"}
+ ]
+ }
+ ]
+}
\ No newline at end of file
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 9310762..f6512a6 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -37,12 +37,15 @@
import android.app.job.JobWorkItem;
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -54,6 +57,7 @@
import android.os.BatteryStats;
import android.os.BatteryStatsInternal;
import android.os.Binder;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -67,6 +71,7 @@
import android.os.WorkSource;
import android.provider.Settings;
import android.text.format.DateUtils;
+import android.util.ArrayMap;
import android.util.KeyValueListParser;
import android.util.Log;
import android.util.Slog;
@@ -85,6 +90,7 @@
import com.android.server.DeviceIdleInternal;
import com.android.server.FgThread;
import com.android.server.LocalServices;
+import com.android.server.compat.PlatformCompat;
import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
import com.android.server.job.controllers.BackgroundJobsController;
@@ -102,6 +108,9 @@
import com.android.server.job.restrictions.ThermalStatusRestriction;
import com.android.server.usage.AppStandbyInternal;
import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
+import com.android.server.utils.quota.Categorizer;
+import com.android.server.utils.quota.Category;
+import com.android.server.utils.quota.CountQuotaTracker;
import libcore.util.EmptyArray;
@@ -145,6 +154,16 @@
/** The maximum number of jobs that we allow an unprivileged app to schedule */
private static final int MAX_JOBS_PER_APP = 100;
+ /**
+ * {@link #schedule(JobInfo)}, {@link #scheduleAsPackage(JobInfo, String, int, String)}, and
+ * {@link #enqueue(JobInfo, JobWorkItem)} will throw a {@link IllegalStateException} if the app
+ * calls the APIs too frequently.
+ */
+ @ChangeId
+ // This means the change will be enabled for target SDK larger than 29 (Q), meaning R and up.
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
+ protected static final long CRASH_ON_EXCEEDED_LIMIT = 144363383L;
+
@VisibleForTesting
public static Clock sSystemClock = Clock.systemUTC();
@@ -237,6 +256,10 @@
*/
private final List<JobRestriction> mJobRestrictions;
+ private final CountQuotaTracker mQuotaTracker;
+ private static final String QUOTA_TRACKER_SCHEDULE_TAG = ".schedule()";
+ private final PlatformCompat mPlatformCompat;
+
/**
* Queue of pending jobs. The JobServiceContext class will receive jobs from this list
* when ready to execute them.
@@ -276,6 +299,11 @@
final SparseIntArray mBackingUpUids = new SparseIntArray();
/**
+ * Cache of debuggable app status.
+ */
+ final ArrayMap<String, Boolean> mDebuggableApps = new ArrayMap<>();
+
+ /**
* Named indices into standby bucket arrays, for clarity in referring to
* specific buckets' bookkeeping.
*/
@@ -315,6 +343,10 @@
final StateController sc = mControllers.get(controller);
sc.onConstantsUpdatedLocked();
}
+ mQuotaTracker.setEnabled(mConstants.ENABLE_API_QUOTAS);
+ mQuotaTracker.setCountLimit(Category.SINGLE_CATEGORY,
+ mConstants.API_QUOTA_SCHEDULE_COUNT,
+ mConstants.API_QUOTA_SCHEDULE_WINDOW_MS);
} catch (IllegalArgumentException e) {
// Failed to parse the settings string, log this and move on
// with defaults.
@@ -466,6 +498,11 @@
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";
+ private static final String KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION =
+ "aq_schedule_throw_exception";
private static final int DEFAULT_MIN_IDLE_COUNT = 1;
private static final int DEFAULT_MIN_CHARGING_COUNT = 1;
@@ -484,6 +521,10 @@
private static final long DEFAULT_MIN_EXP_BACKOFF_TIME = 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;
+ private static final int DEFAULT_API_QUOTA_SCHEDULE_COUNT = 500;
+ private static final long DEFAULT_API_QUOTA_SCHEDULE_WINDOW_MS = MINUTE_IN_MILLIS;
+ private static final boolean DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION = true;
/**
* Minimum # of idle jobs that must be ready in order to force the JMS to schedule things
@@ -618,6 +659,24 @@
*/
public float CONN_PREFETCH_RELAX_FRAC = DEFAULT_CONN_PREFETCH_RELAX_FRAC;
+ /**
+ * Whether to enable quota limits on APIs.
+ */
+ public boolean ENABLE_API_QUOTAS = DEFAULT_ENABLE_API_QUOTAS;
+ /**
+ * The maximum number of schedule() calls an app can make in a set amount of time.
+ */
+ public int API_QUOTA_SCHEDULE_COUNT = DEFAULT_API_QUOTA_SCHEDULE_COUNT;
+ /**
+ * The time window that {@link #API_QUOTA_SCHEDULE_COUNT} should be evaluated over.
+ */
+ public long API_QUOTA_SCHEDULE_WINDOW_MS = DEFAULT_API_QUOTA_SCHEDULE_WINDOW_MS;
+ /**
+ * Whether to throw an exception when an app hits its schedule quota limit.
+ */
+ public boolean API_QUOTA_SCHEDULE_THROW_EXCEPTION =
+ DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION;
+
private final KeyValueListParser mParser = new KeyValueListParser(',');
void updateConstantsLocked(String value) {
@@ -678,6 +737,16 @@
DEFAULT_CONN_CONGESTION_DELAY_FRAC);
CONN_PREFETCH_RELAX_FRAC = mParser.getFloat(KEY_CONN_PREFETCH_RELAX_FRAC,
DEFAULT_CONN_PREFETCH_RELAX_FRAC);
+
+ ENABLE_API_QUOTAS = mParser.getBoolean(KEY_ENABLE_API_QUOTAS,
+ DEFAULT_ENABLE_API_QUOTAS);
+ 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(
+ KEY_API_QUOTA_SCHEDULE_WINDOW_MS, DEFAULT_API_QUOTA_SCHEDULE_WINDOW_MS);
+ API_QUOTA_SCHEDULE_THROW_EXCEPTION = mParser.getBoolean(
+ KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION,
+ DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION);
}
void dump(IndentingPrintWriter pw) {
@@ -716,6 +785,12 @@
pw.printPair(KEY_CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC).println();
pw.printPair(KEY_CONN_PREFETCH_RELAX_FRAC, CONN_PREFETCH_RELAX_FRAC).println();
+ pw.printPair(KEY_ENABLE_API_QUOTAS, ENABLE_API_QUOTAS).println();
+ pw.printPair(KEY_API_QUOTA_SCHEDULE_COUNT, API_QUOTA_SCHEDULE_COUNT).println();
+ pw.printPair(KEY_API_QUOTA_SCHEDULE_WINDOW_MS, API_QUOTA_SCHEDULE_WINDOW_MS).println();
+ pw.printPair(KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION,
+ API_QUOTA_SCHEDULE_THROW_EXCEPTION).println();
+
pw.decreaseIndent();
}
@@ -746,6 +821,12 @@
proto.write(ConstantsProto.MIN_EXP_BACKOFF_TIME_MS, MIN_EXP_BACKOFF_TIME);
proto.write(ConstantsProto.CONN_CONGESTION_DELAY_FRAC, CONN_CONGESTION_DELAY_FRAC);
proto.write(ConstantsProto.CONN_PREFETCH_RELAX_FRAC, CONN_PREFETCH_RELAX_FRAC);
+
+ proto.write(ConstantsProto.ENABLE_API_QUOTAS, ENABLE_API_QUOTAS);
+ proto.write(ConstantsProto.API_QUOTA_SCHEDULE_COUNT, API_QUOTA_SCHEDULE_COUNT);
+ proto.write(ConstantsProto.API_QUOTA_SCHEDULE_WINDOW_MS, API_QUOTA_SCHEDULE_WINDOW_MS);
+ proto.write(ConstantsProto.API_QUOTA_SCHEDULE_THROW_EXCEPTION,
+ API_QUOTA_SCHEDULE_THROW_EXCEPTION);
}
}
@@ -847,6 +928,7 @@
for (int c = 0; c < mControllers.size(); ++c) {
mControllers.get(c).onAppRemovedLocked(pkgName, pkgUid);
}
+ mDebuggableApps.remove(pkgName);
}
}
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
@@ -972,6 +1054,45 @@
public int scheduleAsPackage(JobInfo job, JobWorkItem work, int uId, String packageName,
int userId, String tag) {
+ final String pkg = packageName == null ? job.getService().getPackageName() : packageName;
+ if (!mQuotaTracker.isWithinQuota(userId, pkg, QUOTA_TRACKER_SCHEDULE_TAG)) {
+ Slog.e(TAG, userId + "-" + pkg + " has called schedule() too many times");
+ // TODO(b/145551233): attempt to restrict app
+ if (mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION
+ && mPlatformCompat.isChangeEnabledByPackageName(
+ CRASH_ON_EXCEEDED_LIMIT, pkg, userId)) {
+ final boolean isDebuggable;
+ synchronized (mLock) {
+ if (!mDebuggableApps.containsKey(packageName)) {
+ try {
+ final ApplicationInfo appInfo = AppGlobals.getPackageManager()
+ .getApplicationInfo(pkg, 0, userId);
+ if (appInfo != null) {
+ mDebuggableApps.put(packageName,
+ (appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
+ } else {
+ return JobScheduler.RESULT_FAILURE;
+ }
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ isDebuggable = mDebuggableApps.get(packageName);
+ }
+ if (isDebuggable) {
+ // Only throw the exception for debuggable apps.
+ throw new IllegalStateException(
+ "schedule()/enqueue() called more than "
+ + mQuotaTracker.getLimit(Category.SINGLE_CATEGORY)
+ + " times in the past "
+ + mQuotaTracker.getWindowSizeMs(Category.SINGLE_CATEGORY)
+ + "ms");
+ }
+ }
+ return JobScheduler.RESULT_FAILURE;
+ }
+ mQuotaTracker.noteEvent(userId, pkg, QUOTA_TRACKER_SCHEDULE_TAG);
+
try {
if (ActivityManager.getService().isAppStartModeDisabled(uId,
job.getService().getPackageName())) {
@@ -1296,6 +1417,12 @@
// Set up the app standby bucketing tracker
mStandbyTracker = new StandbyTracker();
mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
+ mPlatformCompat =
+ (PlatformCompat) ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
+ mQuotaTracker = new CountQuotaTracker(context, Categorizer.SINGLE_CATEGORIZER);
+ mQuotaTracker.setCountLimit(Category.SINGLE_CATEGORY,
+ mConstants.API_QUOTA_SCHEDULE_COUNT,
+ mConstants.API_QUOTA_SCHEDULE_WINDOW_MS);
AppStandbyInternal appStandby = LocalServices.getService(AppStandbyInternal.class);
appStandby.addListener(mStandbyTracker);
@@ -2745,7 +2872,7 @@
return new ParceledListSlice<>(snapshots);
}
}
- };
+ }
// Shell command infrastructure: run the given job immediately
int executeRunCommand(String pkgName, int userId, int jobId, boolean force) {
@@ -2968,6 +3095,10 @@
return 0;
}
+ void resetScheduleQuota() {
+ mQuotaTracker.clear();
+ }
+
void triggerDockState(boolean idleState) {
final Intent dockIntent;
if (idleState) {
@@ -3030,6 +3161,9 @@
}
pw.println();
+ mQuotaTracker.dump(pw);
+ pw.println();
+
pw.println("Started users: " + Arrays.toString(mStartedUsers));
pw.print("Registered ");
pw.print(mJobs.size());
@@ -3217,6 +3351,9 @@
for (int u : mStartedUsers) {
proto.write(JobSchedulerServiceDumpProto.STARTED_USERS, u);
}
+
+ mQuotaTracker.dump(proto, JobSchedulerServiceDumpProto.QUOTA_TRACKER);
+
if (mJobs.size() > 0) {
final List<JobStatus> jobs = mJobs.mJobSet.getAllJobs();
sortJobs(jobs);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
index a5c6c01..6becf04 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -66,6 +66,8 @@
return getJobState(pw);
case "heartbeat":
return doHeartbeat(pw);
+ case "reset-schedule-quota":
+ return resetScheduleQuota(pw);
case "trigger-dock-state":
return triggerDockState(pw);
default:
@@ -344,6 +346,18 @@
return -1;
}
+ private int resetScheduleQuota(PrintWriter pw) throws Exception {
+ checkPermission("reset schedule quota");
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mInternal.resetScheduleQuota();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ return 0;
+ }
+
private int triggerDockState(PrintWriter pw) throws Exception {
checkPermission("trigger wireless charging dock state");
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
index 82292cf..b9df30a 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
@@ -17,7 +17,7 @@
package com.android.server.usage;
import static android.app.usage.UsageStatsManager.REASON_MAIN_DEFAULT;
-import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED;
+import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_USER;
import static android.app.usage.UsageStatsManager.REASON_MAIN_MASK;
import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED;
import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
@@ -441,7 +441,7 @@
elapsedRealtime, true);
if (idle) {
appUsageHistory.currentBucket = STANDBY_BUCKET_RARE;
- appUsageHistory.bucketingReason = REASON_MAIN_FORCED;
+ appUsageHistory.bucketingReason = REASON_MAIN_FORCED_BY_USER;
} else {
appUsageHistory.currentBucket = STANDBY_BUCKET_ACTIVE;
// This is to pretend that the app was just used, don't freeze the state anymore.
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 58eb589..eb0b54b 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -17,7 +17,8 @@
package com.android.server.usage;
import static android.app.usage.UsageStatsManager.REASON_MAIN_DEFAULT;
-import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED;
+import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_SYSTEM;
+import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_USER;
import static android.app.usage.UsageStatsManager.REASON_MAIN_MASK;
import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED;
import static android.app.usage.UsageStatsManager.REASON_MAIN_TIMEOUT;
@@ -565,7 +566,7 @@
// If the bucket was forced by the user/developer, leave it alone.
// A usage event will be the only way to bring it out of this forced state
- if (oldMainReason == REASON_MAIN_FORCED) {
+ if (oldMainReason == REASON_MAIN_FORCED_BY_USER) {
return;
}
final int oldBucket = app.currentBucket;
@@ -783,7 +784,7 @@
// Inform listeners if necessary
if (previouslyIdle != stillIdle) {
maybeInformListeners(packageName, userId, elapsedRealtime, standbyBucket,
- REASON_MAIN_FORCED, false);
+ REASON_MAIN_FORCED_BY_USER, false);
if (!stillIdle) {
notifyBatteryStats(packageName, userId, idle);
}
@@ -1030,8 +1031,17 @@
callingPid, callingUid, userId, false, true, "setAppStandbyBucket", null);
final boolean shellCaller = callingUid == Process.ROOT_UID
|| callingUid == Process.SHELL_UID;
- final boolean systemCaller = UserHandle.isCore(callingUid);
- final int reason = systemCaller ? REASON_MAIN_FORCED : REASON_MAIN_PREDICTED;
+ final int reason;
+ // The Settings app runs in the system UID but in a separate process. Assume
+ // things coming from other processes are due to the user.
+ if ((UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) && callingPid != Process.myPid())
+ || shellCaller) {
+ reason = REASON_MAIN_FORCED_BY_USER;
+ } else if (UserHandle.isCore(callingUid)) {
+ reason = REASON_MAIN_FORCED_BY_SYSTEM;
+ } else {
+ reason = REASON_MAIN_PREDICTED;
+ }
final int packageFlags = PackageManager.MATCH_ANY_USER
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_DIRECT_BOOT_AWARE;
@@ -1087,7 +1097,11 @@
}
// If the bucket was forced, don't allow prediction to override
- if ((app.bucketingReason & REASON_MAIN_MASK) == REASON_MAIN_FORCED && predicted) return;
+ if (predicted
+ && ((app.bucketingReason & REASON_MAIN_MASK) == REASON_MAIN_FORCED_BY_USER
+ || (app.bucketingReason & REASON_MAIN_MASK) == REASON_MAIN_FORCED_BY_SYSTEM)) {
+ return;
+ }
// If the bucket is required to stay in a higher state for a specified duration, don't
// override unless the duration has passed
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
new file mode 100644
index 0000000..cf70878
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
@@ -0,0 +1,19 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {"include-filter": "com.android.server.usage"},
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"}
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {"include-filter": "com.android.server.usage"}
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index b3d4198..bbb87ab 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -1502,21 +1502,6 @@
}
}
- private void pullPowerProfile(
- int tagId, long elapsedNanos, long wallClockNanos,
- List<StatsLogEventWrapper> pulledData) {
- PowerProfile powerProfile = new PowerProfile(mContext);
- Objects.requireNonNull(powerProfile);
-
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
- wallClockNanos);
- ProtoOutputStream proto = new ProtoOutputStream();
- powerProfile.dumpDebug(proto);
- proto.flush();
- e.writeStorage(proto.getBytes());
- pulledData.add(e);
- }
-
private void pullBuildInformation(int tagId,
long elapsedNanos, long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
@@ -2261,11 +2246,6 @@
break;
}
- case StatsLog.POWER_PROFILE: {
- pullPowerProfile(tagId, elapsedNanos, wallClockNanos, ret);
- break;
- }
-
case StatsLog.BUILD_INFORMATION: {
pullBuildInformation(tagId, elapsedNanos, wallClockNanos, ret);
break;
diff --git a/api/current.txt b/api/current.txt
index 504f055..ba14b4e6 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -30507,6 +30507,7 @@
method @Nullable public java.security.cert.X509Certificate[] getCaCertificates();
method public java.security.cert.X509Certificate getClientCertificate();
method @Nullable public java.security.cert.X509Certificate[] getClientCertificateChain();
+ method @Nullable public java.security.PrivateKey getClientPrivateKey();
method public String getDomainSuffixMatch();
method public int getEapMethod();
method public String getIdentity();
@@ -39205,6 +39206,7 @@
method @NonNull public static android.app.PendingIntent createWriteRequest(@NonNull android.content.ContentResolver, @NonNull java.util.Collection<android.net.Uri>);
method @Nullable public static android.net.Uri getDocumentUri(@NonNull android.content.Context, @NonNull android.net.Uri);
method @NonNull public static java.util.Set<java.lang.String> getExternalVolumeNames(@NonNull android.content.Context);
+ method public static long getGeneration(@NonNull android.content.Context, @NonNull String);
method public static android.net.Uri getMediaScannerUri();
method @Nullable public static android.net.Uri getMediaUri(@NonNull android.content.Context, @NonNull android.net.Uri);
method @NonNull public static java.util.Set<java.lang.String> getRecentExternalVolumeNames(@NonNull android.content.Context);
@@ -39515,6 +39517,7 @@
field public static final String DISPLAY_NAME = "_display_name";
field public static final String DOCUMENT_ID = "document_id";
field public static final String DURATION = "duration";
+ field public static final String GENERATION = "generation";
field public static final String GENRE = "genre";
field public static final String HEIGHT = "height";
field public static final String INSTANCE_ID = "instance_id";
@@ -45151,6 +45154,9 @@
field public static final String ENABLE_EAP_METHOD_PREFIX_BOOL = "enable_eap_method_prefix_bool";
field public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX";
field public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX";
+ field public static final String IMSI_KEY_AVAILABILITY_INT = "imsi_key_availability_int";
+ field public static final String KEY_5G_ICON_CONFIGURATION_STRING = "5g_icon_configuration_string";
+ field public static final String KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT = "5g_icon_display_grace_period_sec_int";
field public static final String KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY = "5g_nr_ssrsrp_thresholds_int_array";
field public static final String KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY = "5g_nr_ssrsrq_thresholds_int_array";
field public static final String KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY = "5g_nr_sssinr_thresholds_int_array";
@@ -45164,18 +45170,32 @@
field public static final String KEY_ALLOW_LOCAL_DTMF_TONES_BOOL = "allow_local_dtmf_tones_bool";
field public static final String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL = "allow_merge_wifi_calls_when_vowifi_off_bool";
field public static final String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL = "allow_non_emergency_calls_in_ecm_bool";
+ field public static final String KEY_ALLOW_VIDEO_CALLING_FALLBACK_BOOL = "allow_video_calling_fallback_bool";
+ field public static final String KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL = "always_show_data_rat_icon_bool";
field @Deprecated public static final String KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL = "always_show_emergency_alert_onoff_bool";
+ field public static final String KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN = "always_show_primary_signal_bar_in_opportunistic_network_boolean";
field public static final String KEY_APN_EXPAND_BOOL = "apn_expand_bool";
+ field public static final String KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY = "apn_settings_default_apn_types_string_array";
field public static final String KEY_AUTO_RETRY_ENABLED_BOOL = "auto_retry_enabled_bool";
field public static final String KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL = "call_barring_supports_deactivate_all_bool";
field public static final String KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL = "call_barring_supports_password_change_bool";
field public static final String KEY_CALL_BARRING_VISIBILITY_BOOL = "call_barring_visibility_bool";
field public static final String KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY = "call_forwarding_blocks_while_roaming_string_array";
+ field public static final String KEY_CALL_REDIRECTION_SERVICE_COMPONENT_NAME_STRING = "call_redirection_service_component_name_string";
+ field public static final String KEY_CARRIER_ALLOW_DEFLECT_IMS_CALL_BOOL = "carrier_allow_deflect_ims_call_bool";
field public static final String KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL = "carrier_allow_turnoff_ims_bool";
field public static final String KEY_CARRIER_APP_REQUIRED_DURING_SIM_SETUP_BOOL = "carrier_app_required_during_setup_bool";
field public static final String KEY_CARRIER_CALL_SCREENING_APP_STRING = "call_screening_app";
+ field public static final String KEY_CARRIER_CERTIFICATE_STRING_ARRAY = "carrier_certificate_string_array";
+ field public static final String KEY_CARRIER_CONFIG_APPLIED_BOOL = "carrier_config_applied_bool";
field public static final String KEY_CARRIER_CONFIG_VERSION_STRING = "carrier_config_version_string";
field public static final String KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS = "carrier_data_call_permanent_failure_strings";
+ field public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_DCFAILURE_STRING_ARRAY = "carrier_default_actions_on_dcfailure_string_array";
+ field public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_DEFAULT_NETWORK_AVAILABLE = "carrier_default_actions_on_default_network_available_string_array";
+ field public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY = "carrier_default_actions_on_redirection_string_array";
+ field public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET = "carrier_default_actions_on_reset_string_array";
+ field public static final String KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY = "carrier_default_redirection_url_string_array";
+ field public static final String KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL = "carrier_default_wfc_ims_enabled_bool";
field public static final String KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT = "carrier_default_wfc_ims_mode_int";
field public static final String KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT = "carrier_default_wfc_ims_roaming_mode_int";
field @Deprecated public static final String KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL = "carrier_force_disable_etws_cmas_test_bool";
@@ -45188,11 +45208,13 @@
field public static final String KEY_CARRIER_NAME_OVERRIDE_BOOL = "carrier_name_override_bool";
field public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string";
field public static final String KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL = "carrier_rcs_provisioning_required_bool";
+ field public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING = "carrier_settings_activity_component_name_string";
field public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
field public static final String KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL = "carrier_supports_ss_over_ut_bool";
field public static final String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
field public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL = "carrier_ut_provisioning_required_bool";
field public static final String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
+ field public static final String KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL = "carrier_volte_override_wfc_provisioning_bool";
field public static final String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
field public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
field public static final String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
@@ -45206,6 +45228,7 @@
field public static final String KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY = "cdma_nonroaming_networks_string_array";
field public static final String KEY_CDMA_ROAMING_MODE_INT = "cdma_roaming_mode_int";
field public static final String KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY = "cdma_roaming_networks_string_array";
+ field public static final String KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL = "check_pricing_with_carrier_data_roaming_bool";
field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_BOOL = "ci_action_on_sys_update_bool";
field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING = "ci_action_on_sys_update_extra_string";
field public static final String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING = "ci_action_on_sys_update_extra_val_string";
@@ -45215,6 +45238,7 @@
field public static final String KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING = "config_ims_rcs_package_override_string";
field public static final String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
field public static final String KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL = "config_telephony_use_own_number_for_voicemail_bool";
+ field public static final String KEY_CONFIG_WIFI_DISABLE_IN_ECBM = "config_wifi_disable_in_ecbm";
field public static final String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
field public static final String KEY_DATA_LIMIT_NOTIFICATION_BOOL = "data_limit_notification_bool";
field public static final String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
@@ -45226,6 +45250,7 @@
field public static final String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
field public static final String KEY_DIAL_STRING_REPLACE_STRING_ARRAY = "dial_string_replace_string_array";
field public static final String KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL = "disable_cdma_activation_code_bool";
+ field public static final String KEY_DISABLE_CHARGE_INDICATION_BOOL = "disable_charge_indication_bool";
field public static final String KEY_DISABLE_SUPPLEMENTARY_SERVICES_IN_AIRPLANE_MODE_BOOL = "disable_supplementary_services_in_airplane_mode_bool";
field public static final String KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY = "disconnect_cause_play_busytone_int_array";
field public static final String KEY_DISPLAY_HD_AUDIO_PROPERTY_BOOL = "display_hd_audio_property_bool";
@@ -45235,9 +45260,13 @@
field public static final String KEY_EDITABLE_ENHANCED_4G_LTE_BOOL = "editable_enhanced_4g_lte_bool";
field public static final String KEY_EDITABLE_VOICEMAIL_NUMBER_BOOL = "editable_voicemail_number_bool";
field public static final String KEY_EDITABLE_VOICEMAIL_NUMBER_SETTING_BOOL = "editable_voicemail_number_setting_bool";
+ field public static final String KEY_EDITABLE_WFC_MODE_BOOL = "editable_wfc_mode_bool";
+ field public static final String KEY_EDITABLE_WFC_ROAMING_MODE_BOOL = "editable_wfc_roaming_mode_bool";
+ field public static final String KEY_EMERGENCY_NOTIFICATION_DELAY_INT = "emergency_notification_delay_int";
field public static final String KEY_EMERGENCY_NUMBER_PREFIX_STRING_ARRAY = "emergency_number_prefix_string_array";
field public static final String KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL = "enable_dialer_key_vibration_bool";
field public static final String KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL = "enhanced_4g_lte_on_by_default_bool";
+ field public static final String KEY_ENHANCED_4G_LTE_TITLE_VARIANT_INT = "enhanced_4g_lte_title_variant_int";
field public static final String KEY_FORCE_HOME_NETWORK_BOOL = "force_home_network_bool";
field public static final String KEY_GSM_DTMF_TONE_DELAY_INT = "gsm_dtmf_tone_delay_int";
field public static final String KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY = "gsm_nonroaming_networks_string_array";
@@ -45246,13 +45275,17 @@
field public static final String KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
field public static final String KEY_HIDE_ENHANCED_4G_LTE_BOOL = "hide_enhanced_4g_lte_bool";
field public static final String KEY_HIDE_IMS_APN_BOOL = "hide_ims_apn_bool";
+ field public static final String KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL = "hide_lte_plus_data_icon_bool";
field public static final String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool";
field public static final String KEY_HIDE_PRESET_APN_DETAILS_BOOL = "hide_preset_apn_details_bool";
field public static final String KEY_HIDE_SIM_LOCK_SETTINGS_BOOL = "hide_sim_lock_settings_bool";
+ field public static final String KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS = "ignore_data_enabled_changed_for_video_calls";
+ field public static final String KEY_IGNORE_RTT_MODE_SETTING_BOOL = "ignore_rtt_mode_setting_bool";
field public static final String KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL = "ignore_sim_network_locked_events_bool";
field public static final String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
field public static final String KEY_IMS_DTMF_TONE_DELAY_INT = "ims_dtmf_tone_delay_int";
field public static final String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL = "is_ims_conference_size_enforced_bool";
+ field public static final String KEY_LTE_ENABLED_BOOL = "lte_enabled_bool";
field public static final String KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY = "lte_rsrq_thresholds_int_array";
field public static final String KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY = "lte_rssnr_thresholds_int_array";
field public static final String KEY_MDN_IS_ADDITIONAL_VOICEMAIL_NUMBER_BOOL = "mdn_is_additional_voicemail_number_bool";
@@ -45288,6 +45321,7 @@
field public static final String KEY_MMS_UA_PROF_URL_STRING = "uaProfUrl";
field public static final String KEY_MMS_USER_AGENT_STRING = "userAgent";
field public static final String KEY_MONTHLY_DATA_CYCLE_DAY_INT = "monthly_data_cycle_day_int";
+ field public static final String KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL = "only_auto_select_in_home_network";
field public static final String KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY = "only_single_dc_allowed_int_array";
field public static final String KEY_OPERATOR_SELECTION_EXPAND_BOOL = "operator_selection_expand_bool";
field public static final String KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG = "opportunistic_network_data_switch_hysteresis_time_long";
@@ -45301,15 +45335,24 @@
field public static final String KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL = "prevent_clir_activation_and_deactivation_code_bool";
field public static final String KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY = "radio_restart_failure_causes_int_array";
field public static final String KEY_RCS_CONFIG_SERVER_URL_STRING = "rcs_config_server_url_string";
+ field public static final String KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY = "read_only_apn_fields_string_array";
+ field public static final String KEY_READ_ONLY_APN_TYPES_STRING_ARRAY = "read_only_apn_types_string_array";
field public static final String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
field @Deprecated public static final String KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL = "restart_radio_on_pdp_fail_regular_deactivation_bool";
field public static final String KEY_RTT_SUPPORTED_BOOL = "rtt_supported_bool";
+ field public static final String KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL = "show_4g_for_3g_data_icon_bool";
+ field public static final String KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL = "show_4g_for_lte_data_icon_bool";
field public static final String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
+ field public static final String KEY_SHOW_BLOCKING_PAY_PHONE_OPTION_BOOL = "show_blocking_pay_phone_option_bool";
field public static final String KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL = "show_call_blocking_disabled_notification_always_bool";
+ field public static final String KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING = "show_carrier_data_icon_pattern_string";
field public static final String KEY_SHOW_CDMA_CHOICES_BOOL = "show_cdma_choices_bool";
field public static final String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool";
+ field public static final String KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL = "show_ims_registration_status_bool";
field public static final String KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL = "show_onscreen_dial_button_bool";
field public static final String KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL = "show_signal_strength_in_sim_status_bool";
+ field public static final String KEY_SHOW_VIDEO_CALL_CHARGES_ALERT_DIALOG_BOOL = "show_video_call_charges_alert_dialog_bool";
+ field public static final String KEY_SHOW_WFC_LOCATION_PRIVACY_POLICY_BOOL = "show_wfc_location_privacy_policy_bool";
field public static final String KEY_SIMPLIFIED_NETWORK_SETTINGS_BOOL = "simplified_network_settings_bool";
field public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
field public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool";
@@ -45317,14 +45360,20 @@
field public static final String KEY_SUPPORT_CLIR_NETWORK_DEFAULT_BOOL = "support_clir_network_default_bool";
field public static final String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
field public static final String KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL = "support_emergency_sms_over_ims_bool";
+ field public static final String KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL = "support_enhanced_call_blocking_bool";
+ field public static final String KEY_SUPPORT_IMS_CONFERENCE_EVENT_PACKAGE_BOOL = "support_ims_conference_event_package_bool";
field public static final String KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL = "support_pause_ims_video_calls_bool";
field public static final String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool";
+ field public static final String KEY_SUPPORT_TDSCDMA_BOOL = "support_tdscdma_bool";
+ field public static final String KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY = "support_tdscdma_roaming_networks_string_array";
field public static final String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool";
field public static final String KEY_TTY_SUPPORTED_BOOL = "tty_supported_bool";
+ field public static final String KEY_UNLOGGABLE_NUMBERS_STRING_ARRAY = "unloggable_numbers_string_array";
field public static final String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
field public static final String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
field public static final String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
field public static final String KEY_USE_RCS_SIP_OPTIONS_BOOL = "use_rcs_sip_options_bool";
+ field public static final String KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL = "use_wfc_home_network_mode_in_roaming_network_bool";
field public static final String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
field public static final String KEY_VOICE_PRIVACY_DISABLE_UI_BOOL = "voice_privacy_disable_ui_bool";
field public static final String KEY_VOLTE_REPLACEMENT_RAT_INT = "volte_replacement_rat_int";
@@ -45337,6 +45386,8 @@
field public static final String KEY_VVM_PREFETCH_BOOL = "vvm_prefetch_bool";
field public static final String KEY_VVM_SSL_ENABLED_BOOL = "vvm_ssl_enabled_bool";
field public static final String KEY_VVM_TYPE_STRING = "vvm_type_string";
+ field public static final String KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING = "wfc_emergency_address_carrier_app_string";
+ field public static final String KEY_WORLD_MODE_ENABLED_BOOL = "world_mode_enabled_bool";
field public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
}
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index d802177..0a67065 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -1 +1,81 @@
// Signature format: 2.0
+package android.app.timedetector {
+
+ public final class PhoneTimeSuggestion implements android.os.Parcelable {
+ method public void addDebugInfo(@NonNull String);
+ method public void addDebugInfo(@NonNull java.util.List<java.lang.String>);
+ method public int describeContents();
+ method @NonNull public java.util.List<java.lang.String> getDebugInfo();
+ method public int getPhoneId();
+ method @Nullable public android.os.TimestampedValue<java.lang.Long> getUtcTime();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.timedetector.PhoneTimeSuggestion> CREATOR;
+ }
+
+ public static final class PhoneTimeSuggestion.Builder {
+ ctor public PhoneTimeSuggestion.Builder(int);
+ method @NonNull public android.app.timedetector.PhoneTimeSuggestion.Builder addDebugInfo(@NonNull String);
+ method @NonNull public android.app.timedetector.PhoneTimeSuggestion build();
+ method @NonNull public android.app.timedetector.PhoneTimeSuggestion.Builder setUtcTime(@Nullable android.os.TimestampedValue<java.lang.Long>);
+ }
+
+ public class TimeDetector {
+ method @RequiresPermission("android.permission.SUGGEST_PHONE_TIME_AND_ZONE") public void suggestPhoneTime(@NonNull android.app.timedetector.PhoneTimeSuggestion);
+ }
+
+}
+
+package android.app.timezonedetector {
+
+ public final class PhoneTimeZoneSuggestion implements android.os.Parcelable {
+ method public void addDebugInfo(@NonNull String);
+ method public void addDebugInfo(@NonNull java.util.List<java.lang.String>);
+ method @NonNull public static android.app.timezonedetector.PhoneTimeZoneSuggestion createEmptySuggestion(int, @NonNull String);
+ method public int describeContents();
+ method @NonNull public java.util.List<java.lang.String> getDebugInfo();
+ method public int getMatchType();
+ method public int getPhoneId();
+ method public int getQuality();
+ method @Nullable public String getZoneId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.timezonedetector.PhoneTimeZoneSuggestion> CREATOR;
+ field public static final int MATCH_TYPE_EMULATOR_ZONE_ID = 4; // 0x4
+ field public static final int MATCH_TYPE_NA = 0; // 0x0
+ field public static final int MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET = 3; // 0x3
+ field public static final int MATCH_TYPE_NETWORK_COUNTRY_ONLY = 2; // 0x2
+ field public static final int MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY = 5; // 0x5
+ field public static final int QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS = 3; // 0x3
+ field public static final int QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET = 2; // 0x2
+ field public static final int QUALITY_NA = 0; // 0x0
+ field public static final int QUALITY_SINGLE_ZONE = 1; // 0x1
+ }
+
+ public static final class PhoneTimeZoneSuggestion.Builder {
+ ctor public PhoneTimeZoneSuggestion.Builder(int);
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion.Builder addDebugInfo(@NonNull String);
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion build();
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion.Builder setMatchType(int);
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion.Builder setQuality(int);
+ method @NonNull public android.app.timezonedetector.PhoneTimeZoneSuggestion.Builder setZoneId(@Nullable String);
+ }
+
+ public class TimeZoneDetector {
+ method @RequiresPermission("android.permission.SUGGEST_PHONE_TIME_AND_ZONE") public void suggestPhoneTimeZone(@NonNull android.app.timezonedetector.PhoneTimeZoneSuggestion);
+ }
+
+}
+
+package android.os {
+
+ public final class TimestampedValue<T> implements android.os.Parcelable {
+ ctor public TimestampedValue(long, @Nullable T);
+ method public int describeContents();
+ method public long getReferenceTimeMillis();
+ method @Nullable public T getValue();
+ method public static long referenceTimeDifference(@NonNull android.os.TimestampedValue<?>, @NonNull android.os.TimestampedValue<?>);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.os.TimestampedValue<?>> CREATOR;
+ }
+
+}
+
diff --git a/api/system-current.txt b/api/system-current.txt
index 789d86f..71d1a38 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -208,6 +208,7 @@
field public static final String STOP_APP_SWITCHES = "android.permission.STOP_APP_SWITCHES";
field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME";
field public static final String SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON = "android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON";
+ field public static final String SUGGEST_PHONE_TIME_AND_ZONE = "android.permission.SUGGEST_PHONE_TIME_AND_ZONE";
field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
field public static final String SYSTEM_CAMERA = "android.permission.SYSTEM_CAMERA";
field public static final String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED";
@@ -327,6 +328,7 @@
method public void setDeviceLocales(@NonNull android.os.LocaleList);
method @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS) public static void setPersistentVrThread(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean switchUser(@NonNull android.os.UserHandle);
+ method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String);
}
public static interface ActivityManager.OnUidImportanceListener {
@@ -4816,6 +4818,7 @@
field public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; // 0xd
field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
field public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
+ field public static final int TYPE_NONE = -1; // 0xffffffff
}
public abstract static class ConnectivityManager.OnStartTetheringCallback {
@@ -4951,12 +4954,36 @@
field @NonNull public static final android.os.Parcelable.Creator<android.net.MatchAllNetworkSpecifier> CREATOR;
}
+ public final class NattKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
+ ctor public NattKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[]) throws android.net.InvalidPacketException;
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.NattKeepalivePacketData> CREATOR;
+ }
+
public class Network implements android.os.Parcelable {
ctor public Network(@NonNull android.net.Network);
method @NonNull public android.net.Network getPrivateDnsBypassingCopy();
field public final int netId;
}
+ public final class NetworkAgentConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public String getSubscriberId();
+ method public boolean isNat64DetectionEnabled();
+ method public boolean isProvisioningNotificationEnabled();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkAgentConfig> CREATOR;
+ }
+
+ public static class NetworkAgentConfig.Builder {
+ ctor public NetworkAgentConfig.Builder();
+ method @NonNull public android.net.NetworkAgentConfig build();
+ method @NonNull public android.net.NetworkAgentConfig.Builder disableNat64Detection();
+ method @NonNull public android.net.NetworkAgentConfig.Builder disableProvisioningNotification();
+ method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String);
+ }
+
public final class NetworkCapabilities implements android.os.Parcelable {
method public boolean deduceRestrictedCapability();
method @NonNull public int[] getTransportTypes();
@@ -5015,6 +5042,9 @@
field @Deprecated public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
field public static final String EXTRA_NEW_SCORER = "newScorer";
field @Deprecated public static final String EXTRA_PACKAGE_NAME = "packageName";
+ field public static final int SCORE_FILTER_CURRENT_NETWORK = 1; // 0x1
+ field public static final int SCORE_FILTER_NONE = 0; // 0x0
+ field public static final int SCORE_FILTER_SCAN_RESULTS = 2; // 0x2
}
public static interface NetworkScoreManager.NetworkScoreCallback {
@@ -5892,6 +5922,7 @@
}
public class ScanResult implements android.os.Parcelable {
+ ctor public ScanResult();
field public static final int CIPHER_CCMP = 3; // 0x3
field public static final int CIPHER_GCMP_256 = 4; // 0x4
field public static final int CIPHER_NONE = 0; // 0x0
@@ -6008,6 +6039,7 @@
method @Deprecated public static boolean isMetered(@Nullable android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiInfo);
method @Deprecated public boolean isNoInternetAccessExpected();
method @Deprecated public void setIpConfiguration(@Nullable android.net.IpConfiguration);
+ method @Deprecated public void setNetworkSelectionStatus(@NonNull android.net.wifi.WifiConfiguration.NetworkSelectionStatus);
method @Deprecated public void setProxy(@NonNull android.net.IpConfiguration.ProxySettings, @NonNull android.net.ProxyInfo);
field @Deprecated public static final int AP_BAND_2GHZ = 0; // 0x0
field @Deprecated public static final int AP_BAND_5GHZ = 1; // 0x1
@@ -6052,6 +6084,7 @@
method @Deprecated public boolean getHasEverConnected();
method @Deprecated @Nullable public static String getNetworkDisableReasonString(int);
method @Deprecated public int getNetworkSelectionDisableReason();
+ method @Deprecated public int getNetworkSelectionStatus();
method @Deprecated @NonNull public String getNetworkStatusString();
method @Deprecated public boolean isNetworkEnabled();
method @Deprecated public boolean isNetworkPermanentlyDisabled();
@@ -6066,6 +6099,16 @@
field @Deprecated public static final int DISABLED_NO_INTERNET_TEMPORARY = 4; // 0x4
field @Deprecated public static final int NETWORK_SELECTION_DISABLED_MAX = 10; // 0xa
field @Deprecated public static final int NETWORK_SELECTION_ENABLE = 0; // 0x0
+ field @Deprecated public static final int NETWORK_SELECTION_ENABLED = 0; // 0x0
+ field @Deprecated public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED = 2; // 0x2
+ field @Deprecated public static final int NETWORK_SELECTION_TEMPORARY_DISABLED = 1; // 0x1
+ }
+
+ @Deprecated public static final class WifiConfiguration.NetworkSelectionStatus.Builder {
+ ctor @Deprecated public WifiConfiguration.NetworkSelectionStatus.Builder();
+ method @Deprecated @NonNull public android.net.wifi.WifiConfiguration.NetworkSelectionStatus build();
+ method @Deprecated @NonNull public android.net.wifi.WifiConfiguration.NetworkSelectionStatus.Builder setNetworkSelectionDisableReason(int);
+ method @Deprecated @NonNull public android.net.wifi.WifiConfiguration.NetworkSelectionStatus.Builder setNetworkSelectionStatus(int);
}
@Deprecated public static class WifiConfiguration.RecentFailure {
@@ -6110,6 +6153,15 @@
field public static final int INVALID_RSSI = -127; // 0xffffff81
}
+ public static final class WifiInfo.Builder {
+ ctor public WifiInfo.Builder();
+ method @NonNull public android.net.wifi.WifiInfo build();
+ method @NonNull public android.net.wifi.WifiInfo.Builder setBssid(@NonNull String);
+ method @NonNull public android.net.wifi.WifiInfo.Builder setNetworkId(int);
+ method @NonNull public android.net.wifi.WifiInfo.Builder setRssi(int);
+ method @NonNull public android.net.wifi.WifiInfo.Builder setSsid(@NonNull byte[]);
+ }
+
public class WifiManager {
method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void addOnWifiUsabilityStatsListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener);
method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void allowAutojoin(int, boolean);
@@ -10641,6 +10693,8 @@
field public static final String EXTRA_ERROR_CODE = "errorCode";
field public static final String EXTRA_PCO_ID = "pcoId";
field public static final String EXTRA_PCO_VALUE = "pcoValue";
+ field public static final String EXTRA_PHONE_IN_ECM_STATE = "android.telephony.extra.PHONE_IN_ECM_STATE";
+ field public static final String EXTRA_PHONE_IN_EMERGENCY_CALL = "android.telephony.extra.PHONE_IN_EMERGENCY_CALL";
field public static final String EXTRA_REDIRECTION_URL = "redirectionUrl";
field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index bb01911..1441d48 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -341,7 +341,7 @@
}
// Pulled events will start at field 10000.
- // Next: 10069
+ // Next: 10070
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000;
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
@@ -411,6 +411,7 @@
NotificationRemoteViews notification_remote_views = 10066;
DangerousPermissionStateSampled dangerous_permission_state_sampled = 10067;
GraphicsStats graphics_stats = 10068;
+ RuntimeAppOpsAccess runtime_app_ops_access = 10069;
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -4118,10 +4119,10 @@
// as UMOUNT_STAT_* from init/reboot.cpp.
// Logged from f/b/services/.../BootReceiver.java.
SHUTDOWN_UMOUNT_STAT = 2;
- // Reprepsents fie system mounting error code for the current boot. Error codes defined
- // as combination of FsStatFlags from system/core/fs_mgr/fs_mgr.cpp.
+ // Reprepsents fie system mounting error code of /data partition for the current boot.
+ // Error codes defined as combination of FsStatFlags from system/core/fs_mgr/fs_mgr.cpp.
// Logged from f/b/services/.../BootReceiver.java.
- FS_MGR_FS_STAT = 3;
+ FS_MGR_FS_STAT_DATA_PARTITION = 3;
}
// Type of the event.
@@ -7086,7 +7087,7 @@
// Uid of the package requesting the op
optional int32 uid = 1 [(is_uid) = true];
- // Nmae of the package performing the op
+ // Name of the package performing the op
optional string package_name = 2;
// operation id; maps to the OP_* constants in AppOpsManager.java
@@ -7872,3 +7873,35 @@
// more apps are running / rendering.
optional bool is_today = 16;
}
+
+/**
+ * Message related to dangerous (runtime) app ops access
+ */
+message RuntimeAppOpsAccess {
+ // Uid of the package accessing app op
+ optional int32 uid = 1 [(is_uid) = true];
+
+ // Name of the package accessing app op
+ optional string package_name = 2;
+
+ // operation id; maps to the OP_* constants in AppOpsManager.java
+ optional int32 op_id = 3;
+
+ // feature id; provided by developer when accessing related API, limited at 50 chars by API.
+ // Features must be provided through manifest using <feature> tag available in R and above.
+ optional string feature_id = 4;
+
+ // message related to app op access, limited to 600 chars by API
+ optional string message = 5;
+
+ enum SamplingStrategy {
+ DEFAULT = 0;
+ UNIFORM = 1;
+ RARELY_USED = 2;
+ }
+
+ // sampling strategy used to collect this message
+ optional SamplingStrategy sampling_strategy = 6;
+}
+
+
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 06046c1..731afe8 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -224,10 +224,6 @@
.coolDownNs = 3 * NS_PER_SEC,
.puller = new StatsCompanionServicePuller(android::util::DISK_IO)}},
- // PowerProfile constants for power model calculations.
- {{.atomTag = android::util::POWER_PROFILE},
- {.puller = new StatsCompanionServicePuller(android::util::POWER_PROFILE)}},
-
// Process cpu stats. Min cool-down is 5 sec, inline with what AcitivityManagerService uses.
{{.atomTag = android::util::PROCESS_CPU_TIME},
{.coolDownNs = 5 * NS_PER_SEC /* min cool-down in seconds*/,
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 8fe2f12..f2702a8 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -25,6 +25,7 @@
import android.annotation.Size;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.UserHandleAware;
import android.app.Activity;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
@@ -40,6 +41,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Parcelable;
+import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -528,12 +530,9 @@
* authenticator known to the AccountManager service. Empty (never
* null) if no authenticators are known.
*/
+ @UserHandleAware
public AuthenticatorDescription[] getAuthenticatorTypes() {
- try {
- return mService.getAuthenticatorTypes(UserHandle.getCallingUserId());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getAuthenticatorTypesAsUser(mContext.getUserId());
}
/**
@@ -584,13 +583,10 @@
* @return An array of {@link Account}, one for each account. Empty (never null) if no accounts
* have been added.
*/
+ @UserHandleAware
@NonNull
public Account[] getAccounts() {
- try {
- return mService.getAccounts(null, mContext.getOpPackageName());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getAccountsAsUser(mContext.getUserId());
}
/**
@@ -708,6 +704,7 @@
* @return An array of {@link Account}, one per matching account. Empty (never null) if no
* accounts of the specified type have been added.
*/
+ @UserHandleAware
@NonNull
public Account[] getAccountsByType(String type) {
return getAccountsByTypeAsUser(type, mContext.getUser());
@@ -1183,23 +1180,11 @@
* {@link #removeAccount(Account, Activity, AccountManagerCallback, Handler)}
* instead
*/
+ @UserHandleAware
@Deprecated
public AccountManagerFuture<Boolean> removeAccount(final Account account,
AccountManagerCallback<Boolean> callback, Handler handler) {
- if (account == null) throw new IllegalArgumentException("account is null");
- return new Future2Task<Boolean>(handler, callback) {
- @Override
- public void doWork() throws RemoteException {
- mService.removeAccount(mResponse, account, false);
- }
- @Override
- public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
- if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
- throw new AuthenticatorException("no result in response");
- }
- return bundle.getBoolean(KEY_BOOLEAN_RESULT);
- }
- }.start();
+ return removeAccountAsUser(account, callback, handler, mContext.getUser());
}
/**
@@ -1243,15 +1228,10 @@
* adding accounts (of this type) has been disabled by policy
* </ul>
*/
+ @UserHandleAware
public AccountManagerFuture<Bundle> removeAccount(final Account account,
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
- if (account == null) throw new IllegalArgumentException("account is null");
- return new AmsTask(activity, handler, callback) {
- @Override
- public void doWork() throws RemoteException {
- mService.removeAccount(mResponse, account, activity != null);
- }
- }.start();
+ return removeAccountAsUser(account, activity, callback, handler, mContext.getUser());
}
/**
@@ -1841,24 +1821,30 @@
* creating a new account, usually because of network trouble
* </ul>
*/
+ @UserHandleAware
public AccountManagerFuture<Bundle> addAccount(final String accountType,
final String authTokenType, final String[] requiredFeatures,
final Bundle addAccountOptions,
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
- if (accountType == null) throw new IllegalArgumentException("accountType is null");
- final Bundle optionsIn = new Bundle();
- if (addAccountOptions != null) {
- optionsIn.putAll(addAccountOptions);
- }
- optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
-
- return new AmsTask(activity, handler, callback) {
- @Override
- public void doWork() throws RemoteException {
- mService.addAccount(mResponse, accountType, authTokenType,
- requiredFeatures, activity != null, optionsIn);
+ if (Process.myUserHandle().equals(mContext.getUser())) {
+ if (accountType == null) throw new IllegalArgumentException("accountType is null");
+ final Bundle optionsIn = new Bundle();
+ if (addAccountOptions != null) {
+ optionsIn.putAll(addAccountOptions);
}
- }.start();
+ optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
+
+ return new AmsTask(activity, handler, callback) {
+ @Override
+ public void doWork() throws RemoteException {
+ mService.addAccount(mResponse, accountType, authTokenType,
+ requiredFeatures, activity != null, optionsIn);
+ }
+ }.start();
+ } else {
+ return addAccountAsUser(accountType, authTokenType, requiredFeatures, addAccountOptions,
+ activity, callback, handler, mContext.getUser());
+ }
}
/**
@@ -2002,6 +1988,7 @@
* verifying the password, usually because of network trouble
* </ul>
*/
+ @UserHandleAware
public AccountManagerFuture<Bundle> confirmCredentials(final Account account,
final Bundle options,
final Activity activity,
@@ -3209,6 +3196,7 @@
* </ul>
* @see #startAddAccountSession and #startUpdateCredentialsSession
*/
+ @UserHandleAware
public AccountManagerFuture<Bundle> finishSession(
final Bundle sessionBundle,
final Activity activity,
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index 0127138..ce68e08 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -34,7 +34,6 @@
String getPassword(in Account account);
String getUserData(in Account account, String key);
AuthenticatorDescription[] getAuthenticatorTypes(int userId);
- Account[] getAccounts(String accountType, String opPackageName);
Account[] getAccountsForPackage(String packageName, int uid, String opPackageName);
Account[] getAccountsByTypeForPackage(String type, String packageName, String opPackageName);
Account[] getAccountsAsUser(String accountType, int userId, String opPackageName);
@@ -45,8 +44,6 @@
void getAccountsByFeatures(in IAccountManagerResponse response, String accountType,
in String[] features, String opPackageName);
boolean addAccountExplicitly(in Account account, String password, in Bundle extras);
- void removeAccount(in IAccountManagerResponse response, in Account account,
- boolean expectActivityLaunch);
void removeAccountAsUser(in IAccountManagerResponse response, in Account account,
boolean expectActivityLaunch, int userId);
boolean removeAccountExplicitly(in Account account);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9aef20b..c3b07c8 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -4073,6 +4073,29 @@
}
/**
+ * Updates mcc mnc configuration and applies changes to the entire system.
+ *
+ * @param mcc mcc configuration to update.
+ * @param mnc mnc configuration to update.
+ * @throws RemoteException; IllegalArgumentException if mcc or mnc is null;
+ * @return Returns {@code true} if the configuration was updated successfully;
+ * {@code false} otherwise.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION)
+ public boolean updateMccMncConfiguration(@NonNull String mcc, @NonNull String mnc) {
+ if (mcc == null || mnc == null) {
+ throw new IllegalArgumentException("mcc or mnc cannot be null.");
+ }
+ try {
+ return getService().updateMccMncConfiguration(mcc, mnc);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Logs out current current foreground user by switching to the system user and stopping the
* user being switched from.
* @hide
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index e8494c4..bd6baec 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -188,6 +188,16 @@
*/
@UnsupportedAppUsage
boolean updateConfiguration(in Configuration values);
+ /**
+ * Updates mcc mnc configuration and applies changes to the entire system.
+ *
+ * @param mcc mcc configuration to update.
+ * @param mnc mnc configuration to update.
+ * @throws RemoteException; IllegalArgumentException if mcc or mnc is null.
+ * @return Returns {@code true} if the configuration was updated;
+ * {@code false} otherwise.
+ */
+ boolean updateMccMncConfiguration(in String mcc, in String mnc);
boolean stopServiceToken(in ComponentName className, in IBinder token, int startId);
@UnsupportedAppUsage
void setProcessLimit(int max);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 69640b8..caaa686 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1992,16 +1992,6 @@
public static final int CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER = 14;
/**
- * Result code for {@link #checkProvisioningPreCondition}.
- *
- * <p>Returned for {@link #ACTION_PROVISION_MANAGED_PROFILE} when adding a managed profile is
- * disallowed by {@link UserManager#DISALLOW_ADD_MANAGED_PROFILE}.
- *
- * @hide
- */
- public static final int CODE_ADD_MANAGED_PROFILE_DISALLOWED = 15;
-
- /**
* Result codes for {@link #checkProvisioningPreCondition} indicating all the provisioning pre
* conditions.
*
@@ -2013,7 +2003,7 @@
CODE_USER_SETUP_COMPLETED, CODE_NOT_SYSTEM_USER, CODE_HAS_PAIRED,
CODE_MANAGED_USERS_NOT_SUPPORTED, CODE_SYSTEM_USER, CODE_CANNOT_ADD_MANAGED_PROFILE,
CODE_NOT_SYSTEM_USER_SPLIT, CODE_DEVICE_ADMIN_NOT_SUPPORTED,
- CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER, CODE_ADD_MANAGED_PROFILE_DISALLOWED
+ CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER
})
public @interface ProvisioningPreCondition {}
diff --git a/core/java/android/app/timedetector/PhoneTimeSuggestion.java b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
index 479e4b4..bd649f8 100644
--- a/core/java/android/app/timedetector/PhoneTimeSuggestion.java
+++ b/core/java/android/app/timedetector/PhoneTimeSuggestion.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.TimestampedValue;
@@ -28,17 +29,23 @@
import java.util.Objects;
/**
- * A time signal from a telephony source. The value can be {@code null} to indicate that the
- * telephony source has entered an "un-opinionated" state and any previously sent suggestions are
- * being withdrawn. When not {@code null}, the value consists of the number of milliseconds elapsed
- * since 1/1/1970 00:00:00 UTC and the time according to the elapsed realtime clock when that number
- * was established. The elapsed realtime clock is considered accurate but volatile, so time signals
- * must not be persisted across device resets.
+ * A time suggestion from an identified telephony source. e.g. from NITZ information from a specific
+ * radio.
+ *
+ * <p>The time value can be {@code null} to indicate that the telephony source has entered an
+ * "un-opinionated" state and any previous suggestions from the source are being withdrawn. When not
+ * {@code null}, the value consists of the number of milliseconds elapsed since 1/1/1970 00:00:00
+ * UTC and the time according to the elapsed realtime clock when that number was established. The
+ * elapsed realtime clock is considered accurate but volatile, so time suggestions must not be
+ * persisted across device resets.
*
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class PhoneTimeSuggestion implements Parcelable {
+ /** @hide */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final @NonNull Parcelable.Creator<PhoneTimeSuggestion> CREATOR =
new Parcelable.Creator<PhoneTimeSuggestion>() {
public PhoneTimeSuggestion createFromParcel(Parcel in) {
@@ -85,15 +92,27 @@
dest.writeList(mDebugInfo);
}
+ /**
+ * Returns an identifier for the source of this suggestion. When a device has several "phones",
+ * i.e. sim slots or equivalent, it is used to identify which one.
+ */
public int getPhoneId() {
return mPhoneId;
}
+ /**
+ * Returns the suggestion. {@code null} means that the caller is no longer sure what time it
+ * is.
+ */
@Nullable
public TimestampedValue<Long> getUtcTime() {
return mUtcTime;
}
+ /**
+ * Returns debug metadata for the suggestion. The information is present in {@link #toString()}
+ * but is not considered for {@link #equals(Object)} and {@link #hashCode()}.
+ */
@NonNull
public List<String> getDebugInfo() {
return mDebugInfo == null
@@ -105,7 +124,7 @@
* information is present in {@link #toString()} but is not considered for
* {@link #equals(Object)} and {@link #hashCode()}.
*/
- public void addDebugInfo(String debugInfo) {
+ public void addDebugInfo(@NonNull String debugInfo) {
if (mDebugInfo == null) {
mDebugInfo = new ArrayList<>();
}
@@ -156,16 +175,19 @@
*
* @hide
*/
- public static class Builder {
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public static final class Builder {
private final int mPhoneId;
- private TimestampedValue<Long> mUtcTime;
- private List<String> mDebugInfo;
+ @Nullable private TimestampedValue<Long> mUtcTime;
+ @Nullable private List<String> mDebugInfo;
+ /** Creates a builder with the specified {@code phoneId}. */
public Builder(int phoneId) {
mPhoneId = phoneId;
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder setUtcTime(@Nullable TimestampedValue<Long> utcTime) {
if (utcTime != null) {
// utcTime can be null, but the value it holds cannot.
@@ -177,6 +199,7 @@
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder addDebugInfo(@NonNull String debugInfo) {
if (mDebugInfo == null) {
mDebugInfo = new ArrayList<>();
@@ -186,6 +209,7 @@
}
/** Returns the {@link PhoneTimeSuggestion}. */
+ @NonNull
public PhoneTimeSuggestion build() {
return new PhoneTimeSuggestion(this);
}
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index 54dd1be..7c29f01 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
@@ -29,8 +30,11 @@
/**
* The interface through which system components can send signals to the TimeDetectorService.
+ *
+ * <p>This class is marked non-final for mockito.
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@SystemService(Context.TIME_DETECTOR_SERVICE)
public class TimeDetector {
private static final String TAG = "timedetector.TimeDetector";
@@ -38,6 +42,7 @@
private final ITimeDetectorService mITimeDetectorService;
+ /** @hide */
public TimeDetector() throws ServiceNotFoundException {
mITimeDetectorService = ITimeDetectorService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.TIME_DETECTOR_SERVICE));
@@ -62,6 +67,8 @@
/**
* Suggests the user's manually entered current time to the detector.
+ *
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE)
public void suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion) {
@@ -77,6 +84,8 @@
/**
* A shared utility method to create a {@link ManualTimeSuggestion}.
+ *
+ * @hide
*/
public static ManualTimeSuggestion createManualTimeSuggestion(long when, String why) {
TimestampedValue<Long> utcTime =
@@ -88,6 +97,8 @@
/**
* Suggests the time according to a network time source like NTP.
+ *
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.SET_TIME)
public void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion) {
diff --git a/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java b/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
index e8162488..d71ffcb 100644
--- a/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
+++ b/core/java/android/app/timezonedetector/PhoneTimeZoneSuggestion.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,12 +31,27 @@
import java.util.Objects;
/**
- * A suggested time zone from a Phone-based signal, e.g. from MCC and NITZ information.
+ * A time zone suggestion from an identified telephony source, e.g. from MCC and NITZ information
+ * associated with a specific radio.
+ *
+ * <p>The time zone ID can be {@code null} to indicate that the telephony source has entered an
+ * "un-opinionated" state and any previous suggestions from that source are being withdrawn.
+ * When not {@code null}, the value consists of a suggested time zone ID and metadata that can be
+ * used to judge quality / certainty of the suggestion.
+ *
+ * <p>{@code matchType} must be set to {@link #MATCH_TYPE_NA} when {@code zoneId} is {@code null},
+ * and one of the other {@code MATCH_TYPE_} values when it is not {@code null}.
+ *
+ * <p>{@code quality} must be set to {@link #QUALITY_NA} when {@code zoneId} is {@code null},
+ * and one of the other {@code QUALITY_} values when it is not {@code null}.
*
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class PhoneTimeZoneSuggestion implements Parcelable {
+ /** @hide */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@NonNull
public static final Creator<PhoneTimeZoneSuggestion> CREATOR =
new Creator<PhoneTimeZoneSuggestion>() {
@@ -58,6 +74,7 @@
return new Builder(phoneId).addDebugInfo(debugInfo).build();
}
+ /** @hide */
@IntDef({ MATCH_TYPE_NA, MATCH_TYPE_NETWORK_COUNTRY_ONLY, MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET,
MATCH_TYPE_EMULATOR_ZONE_ID, MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY })
@Retention(RetentionPolicy.SOURCE)
@@ -90,6 +107,7 @@
*/
public static final int MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY = 5;
+ /** @hide */
@IntDef({ QUALITY_NA, QUALITY_SINGLE_ZONE, QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET,
QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS })
@Retention(RetentionPolicy.SOURCE)
@@ -115,7 +133,7 @@
/**
* The ID of the phone this suggestion is associated with. For multiple-sim devices this
- * helps to establish origin so filtering / stickiness can be implemented.
+ * helps to establish source so filtering / stickiness can be implemented.
*/
private final int mPhoneId;
@@ -123,6 +141,7 @@
* The suggestion. {@code null} means there is no current suggestion and any previous suggestion
* should be forgotten.
*/
+ @Nullable
private final String mZoneId;
/**
@@ -139,9 +158,10 @@
private final int mQuality;
/**
- * Free-form debug information about how the signal was derived. Used for debug only,
+ * Free-form debug information about how the suggestion was derived. Used for debug only,
* intentionally not used in equals(), etc.
*/
+ @Nullable
private List<String> mDebugInfo;
private PhoneTimeZoneSuggestion(Builder builder) {
@@ -182,25 +202,47 @@
return 0;
}
+ /**
+ * Returns an identifier for the source of this suggestion. When a device has several "phones",
+ * i.e. sim slots or equivalent, it is used to identify which one.
+ */
public int getPhoneId() {
return mPhoneId;
}
+ /**
+ * Returns the suggested time zone Olson ID, e.g. "America/Los_Angeles". {@code null} means that
+ * the caller is no longer sure what the current time zone is. See
+ * {@link PhoneTimeZoneSuggestion} for the associated {@code matchType} / {@code quality} rules.
+ */
@Nullable
public String getZoneId() {
return mZoneId;
}
+ /**
+ * Returns information about how the suggestion was determined which could be used to rank
+ * suggestions when several are available from different sources. See
+ * {@link PhoneTimeZoneSuggestion} for the associated rules.
+ */
@MatchType
public int getMatchType() {
return mMatchType;
}
+ /**
+ * Returns information about the likelihood of the suggested zone being correct. See
+ * {@link PhoneTimeZoneSuggestion} for the associated rules.
+ */
@Quality
public int getQuality() {
return mQuality;
}
+ /**
+ * Returns debug metadata for the suggestion. The information is present in {@link #toString()}
+ * but is not considered for {@link #equals(Object)} and {@link #hashCode()}.
+ */
@NonNull
public List<String> getDebugInfo() {
return mDebugInfo == null
@@ -267,36 +309,43 @@
*
* @hide
*/
- public static class Builder {
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public static final class Builder {
private final int mPhoneId;
- private String mZoneId;
+ @Nullable private String mZoneId;
@MatchType private int mMatchType;
@Quality private int mQuality;
- private List<String> mDebugInfo;
+ @Nullable private List<String> mDebugInfo;
public Builder(int phoneId) {
mPhoneId = phoneId;
}
- /** Returns the builder for call chaining. */
- public Builder setZoneId(String zoneId) {
+ /**
+ * Returns the builder for call chaining.
+ */
+ @NonNull
+ public Builder setZoneId(@Nullable String zoneId) {
mZoneId = zoneId;
return this;
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder setMatchType(@MatchType int matchType) {
mMatchType = matchType;
return this;
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder setQuality(@Quality int quality) {
mQuality = quality;
return this;
}
/** Returns the builder for call chaining. */
+ @NonNull
public Builder addDebugInfo(@NonNull String debugInfo) {
if (mDebugInfo == null) {
mDebugInfo = new ArrayList<>();
@@ -333,6 +382,7 @@
}
/** Returns the {@link PhoneTimeZoneSuggestion}. */
+ @NonNull
public PhoneTimeZoneSuggestion build() {
validate();
return new PhoneTimeZoneSuggestion(this);
diff --git a/core/java/android/app/timezonedetector/TimeZoneDetector.java b/core/java/android/app/timezonedetector/TimeZoneDetector.java
index e165d8a..5b5f311 100644
--- a/core/java/android/app/timezonedetector/TimeZoneDetector.java
+++ b/core/java/android/app/timezonedetector/TimeZoneDetector.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.RemoteException;
@@ -28,8 +29,10 @@
/**
* The interface through which system components can send signals to the TimeZoneDetectorService.
*
+ * <p>This class is non-final for mockito.
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@SystemService(Context.TIME_ZONE_DETECTOR_SERVICE)
public class TimeZoneDetector {
private static final String TAG = "timezonedetector.TimeZoneDetector";
@@ -37,6 +40,7 @@
private final ITimeZoneDetectorService mITimeZoneDetectorService;
+ /** @hide */
public TimeZoneDetector() throws ServiceNotFoundException {
mITimeZoneDetectorService = ITimeZoneDetectorService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.TIME_ZONE_DETECTOR_SERVICE));
@@ -46,7 +50,10 @@
* Suggests the current time zone, determined using telephony signals, to the detector. The
* detector may ignore the signal based on system settings, whether better information is
* available, and so on.
+ *
+ * @hide
*/
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@RequiresPermission(android.Manifest.permission.SUGGEST_PHONE_TIME_AND_ZONE)
public void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion) {
if (DEBUG) {
@@ -62,6 +69,8 @@
/**
* Suggests the current time zone, determined for the user's manually information, to the
* detector. The detector may ignore the signal based on system settings.
+ *
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE)
public void suggestManualTimeZone(@NonNull ManualTimeZoneSuggestion timeZoneSuggestion) {
@@ -77,6 +86,8 @@
/**
* A shared utility method to create a {@link ManualTimeZoneSuggestion}.
+ *
+ * @hide
*/
public static ManualTimeZoneSuggestion createManualTimeZoneSuggestion(String tzId, String why) {
ManualTimeZoneSuggestion suggestion = new ManualTimeZoneSuggestion(tzId);
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 176a181..a60e591 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -163,7 +163,6 @@
/**
* The app spent sufficient time in the old bucket without any substantial event so it reached
* the timeout threshold to have its bucket lowered.
- *
* @hide
*/
public static final int REASON_MAIN_TIMEOUT = 0x0200;
@@ -173,15 +172,25 @@
*/
public static final int REASON_MAIN_USAGE = 0x0300;
/**
- * Forced by a core UID.
+ * Forced by the user/developer, either explicitly or implicitly through some action. If user
+ * action was not involved and this is purely due to the system,
+ * {@link #REASON_MAIN_FORCED_BY_SYSTEM} should be used instead.
* @hide
*/
- public static final int REASON_MAIN_FORCED = 0x0400;
+ public static final int REASON_MAIN_FORCED_BY_USER = 0x0400;
/**
- * Set by a privileged system app.
+ * Set by a privileged system app. This may be overridden by
+ * {@link #REASON_MAIN_FORCED_BY_SYSTEM} or user action.
* @hide
*/
public static final int REASON_MAIN_PREDICTED = 0x0500;
+ /**
+ * Forced by the system, independent of user action. If user action is involved,
+ * {@link #REASON_MAIN_FORCED_BY_USER} should be used instead. When this is used, only
+ * {@link #REASON_MAIN_FORCED_BY_SYSTEM} or user action can change the bucket.
+ * @hide
+ */
+ public static final int REASON_MAIN_FORCED_BY_SYSTEM = 0x0600;
/** @hide */
public static final int REASON_SUB_MASK = 0x00FF;
@@ -1016,7 +1025,10 @@
case REASON_MAIN_DEFAULT:
sb.append("d");
break;
- case REASON_MAIN_FORCED:
+ case REASON_MAIN_FORCED_BY_SYSTEM:
+ sb.append("s");
+ break;
+ case REASON_MAIN_FORCED_BY_USER:
sb.append("f");
break;
case REASON_MAIN_PREDICTED:
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 4bf3e90..c523f65 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -517,7 +517,7 @@
* The absence of a connection type.
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
+ @SystemApi
public static final int TYPE_NONE = -1;
/**
@@ -3169,10 +3169,10 @@
/**
* @hide
* Register a NetworkAgent with ConnectivityService.
- * @return NetID corresponding to NetworkAgent.
+ * @return Network corresponding to NetworkAgent.
*/
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
- public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
+ public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
NetworkCapabilities nc, int score, NetworkAgentConfig config) {
return registerNetworkAgent(messenger, ni, lp, nc, score, config, NetworkProvider.ID_NONE);
}
@@ -3180,10 +3180,10 @@
/**
* @hide
* Register a NetworkAgent with ConnectivityService.
- * @return NetID corresponding to NetworkAgent.
+ * @return Network corresponding to NetworkAgent.
*/
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
- public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
+ public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) {
try {
return mService.registerNetworkAgent(messenger, ni, lp, nc, score, config, providerId);
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 7691beb..186196bd 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -152,7 +152,7 @@
void declareNetworkRequestUnfulfillable(in NetworkRequest request);
- int registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
+ Network registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
in NetworkCapabilities nc, int score, in NetworkAgentConfig config,
in int factorySerialNumber);
diff --git a/core/java/android/net/NattKeepalivePacketData.java b/core/java/android/net/NattKeepalivePacketData.java
index 3fb52f1..bd39c13 100644
--- a/core/java/android/net/NattKeepalivePacketData.java
+++ b/core/java/android/net/NattKeepalivePacketData.java
@@ -16,9 +16,11 @@
package android.net;
-import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
-import static android.net.SocketKeepalive.ERROR_INVALID_PORT;
+import static android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS;
+import static android.net.InvalidPacketException.ERROR_INVALID_PORT;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.net.util.IpUtils;
import android.os.Parcel;
import android.os.Parcelable;
@@ -30,20 +32,22 @@
import java.nio.ByteOrder;
/** @hide */
+@SystemApi
public final class NattKeepalivePacketData extends KeepalivePacketData implements Parcelable {
private static final int IPV4_HEADER_LENGTH = 20;
private static final int UDP_HEADER_LENGTH = 8;
// This should only be constructed via static factory methods, such as
// nattKeepalivePacket
- private NattKeepalivePacketData(InetAddress srcAddress, int srcPort,
- InetAddress dstAddress, int dstPort, byte[] data) throws
+ public NattKeepalivePacketData(@NonNull InetAddress srcAddress, int srcPort,
+ @NonNull InetAddress dstAddress, int dstPort, @NonNull byte[] data) throws
InvalidPacketException {
super(srcAddress, srcPort, dstAddress, dstPort, data);
}
/**
* Factory method to create Nat-T keepalive packet structure.
+ * @hide
*/
public static NattKeepalivePacketData nattKeepalivePacket(
InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort)
@@ -87,7 +91,7 @@
}
/** Write to parcel */
- public void writeToParcel(Parcel out, int flags) {
+ public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeString(srcAddress.getHostAddress());
out.writeString(dstAddress.getHostAddress());
out.writeInt(srcPort);
@@ -95,7 +99,7 @@
}
/** Parcelable Creator */
- public static final Parcelable.Creator<NattKeepalivePacketData> CREATOR =
+ public static final @NonNull Parcelable.Creator<NattKeepalivePacketData> CREATOR =
new Parcelable.Creator<NattKeepalivePacketData>() {
public NattKeepalivePacketData createFromParcel(Parcel in) {
final InetAddress srcAddress =
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index fc72eec..d286204 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -44,9 +44,10 @@
* @hide
*/
public abstract class NetworkAgent {
- // Guaranteed to be valid (not NETID_UNSET), otherwise registerNetworkAgent() would have thrown
- // an exception.
- public final int netId;
+ // Guaranteed to be non-null, otherwise registerNetworkAgent() would have thrown
+ // an exception. Be careful in tests when mocking though.
+ @NonNull
+ public final Network network;
private final Handler mHandler;
private volatile AsyncChannel mAsyncChannel;
@@ -246,7 +247,7 @@
if (VDBG) log("Registering NetworkAgent");
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
- netId = cm.registerNetworkAgent(new Messenger(mHandler), new NetworkInfo(ni),
+ network = cm.registerNetworkAgent(new Messenger(mHandler), new NetworkInfo(ni),
new LinkProperties(lp), new NetworkCapabilities(nc), score, config,
providerId);
}
diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java
index 3a383a4..abc6b67 100644
--- a/core/java/android/net/NetworkAgentConfig.java
+++ b/core/java/android/net/NetworkAgentConfig.java
@@ -18,22 +18,27 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
/**
- * A grab-bag of information (metadata, policies, properties, etc) about a
- * {@link Network}. Since this contains PII, it should not be sent outside the
- * system.
+ * Allows a network transport to provide the system with policy and configuration information about
+ * a particular network when registering a {@link NetworkAgent}. This information cannot change once
+ * the agent is registered.
*
* @hide
*/
-public class NetworkAgentConfig implements Parcelable {
+@SystemApi
+public final class NetworkAgentConfig implements Parcelable {
/**
* If the {@link Network} is a VPN, whether apps are allowed to bypass the
* VPN. This is set by a {@link VpnService} and used by
* {@link ConnectivityManager} when creating a VPN.
+ *
+ * @hide
*/
public boolean allowBypass;
@@ -43,6 +48,8 @@
* ap in the wifi settings to trigger a connection is explicit. A 3rd party app asking to
* connect to a particular access point is also explicit, though this may change in the future
* as we want apps to use the multinetwork apis.
+ *
+ * @hide
*/
public boolean explicitlySelected;
@@ -50,12 +57,16 @@
* Set if the user desires to use this network even if it is unvalidated. This field has meaning
* only if {@link explicitlySelected} is true. If it is, this field must also be set to the
* appropriate value based on previous user choice.
+ *
+ * @hide
*/
public boolean acceptUnvalidated;
/**
* Whether the user explicitly set that this network should be validated even if presence of
* only partial internet connectivity.
+ *
+ * @hide
*/
public boolean acceptPartialConnectivity;
@@ -65,29 +76,62 @@
* procedure, a carrier specific provisioning notification will be placed.
* only one notification should be displayed. This field is set based on
* which notification should be used for provisioning.
+ *
+ * @hide
*/
public boolean provisioningNotificationDisabled;
/**
+ *
+ * @return whether the sign in to network notification is enabled by this configuration.
+ */
+ public boolean isProvisioningNotificationEnabled() {
+ return !provisioningNotificationDisabled;
+ }
+
+ /**
* For mobile networks, this is the subscriber ID (such as IMSI).
+ *
+ * @hide
*/
public String subscriberId;
/**
+ * @return the subscriber ID, or null if none.
+ */
+ @Nullable
+ public String getSubscriberId() {
+ return subscriberId;
+ }
+
+ /**
* Set to skip 464xlat. This means the device will treat the network as IPv6-only and
* will not attempt to detect a NAT64 via RFC 7050 DNS lookups.
+ *
+ * @hide
*/
public boolean skip464xlat;
/**
+ * @return whether NAT64 prefix detection is enabled.
+ */
+ public boolean isNat64DetectionEnabled() {
+ return !skip464xlat;
+ }
+
+ /**
* Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network.
* Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode.
+ *
+ * @hide
*/
public boolean hasShownBroken;
+ /** @hide */
public NetworkAgentConfig() {
}
+ /** @hide */
public NetworkAgentConfig(@Nullable NetworkAgentConfig nac) {
if (nac != null) {
allowBypass = nac.allowBypass;
@@ -99,13 +143,63 @@
}
}
+ /**
+ * Builder class to facilitate constructing {@link NetworkAgentConfig} objects.
+ */
+ public static class Builder {
+ private final NetworkAgentConfig mConfig = new NetworkAgentConfig();
+
+ /**
+ * Sets the subscriber ID for this network.
+ *
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder setSubscriberId(@Nullable String subscriberId) {
+ mConfig.subscriberId = subscriberId;
+ return this;
+ }
+
+ /**
+ * Disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to save power
+ * and reduce idle traffic on networks that are known to be IPv6-only without a NAT64.
+ *
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder disableNat64Detection() {
+ mConfig.skip464xlat = true;
+ return this;
+ }
+
+ /**
+ * Disables the "Sign in to network" notification. Used if the network transport will
+ * perform its own carrier-specific provisioning procedure.
+ *
+ * @return this builder, to facilitate chaining.
+ */
+ @NonNull
+ public Builder disableProvisioningNotification() {
+ mConfig.provisioningNotificationDisabled = true;
+ return this;
+ }
+
+ /**
+ * Returns the constructed {@link NetworkAgentConfig} object.
+ */
+ @NonNull
+ public NetworkAgentConfig build() {
+ return mConfig;
+ }
+ }
+
@Override
public int describeContents() {
return 0;
}
@Override
- public void writeToParcel(Parcel out, int flags) {
+ public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeInt(allowBypass ? 1 : 0);
out.writeInt(explicitlySelected ? 1 : 0);
out.writeInt(acceptUnvalidated ? 1 : 0);
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index f6dc525..428a4ea 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -163,27 +163,26 @@
public static final String EXTRA_NEW_SCORER = "newScorer";
/** @hide */
- @IntDef({CACHE_FILTER_NONE, CACHE_FILTER_CURRENT_NETWORK, CACHE_FILTER_SCAN_RESULTS})
+ @IntDef({SCORE_FILTER_NONE, SCORE_FILTER_CURRENT_NETWORK, SCORE_FILTER_SCAN_RESULTS})
@Retention(RetentionPolicy.SOURCE)
- public @interface CacheUpdateFilter {}
+ public @interface ScoreUpdateFilter {}
/**
- * Do not filter updates sent to the cache.
- * @hide
+ * Do not filter updates sent to the {@link NetworkScoreCallback}].
*/
- public static final int CACHE_FILTER_NONE = 0;
+ public static final int SCORE_FILTER_NONE = 0;
/**
- * Only send cache updates when the network matches the connected network.
- * @hide
+ * Only send updates to the {@link NetworkScoreCallback} when the network matches the connected
+ * network.
*/
- public static final int CACHE_FILTER_CURRENT_NETWORK = 1;
+ public static final int SCORE_FILTER_CURRENT_NETWORK = 1;
/**
- * Only send cache updates when the network is part of the current scan result set.
- * @hide
+ * Only send updates to the {@link NetworkScoreCallback} when the network is part of the
+ * current scan result set.
*/
- public static final int CACHE_FILTER_SCAN_RESULTS = 2;
+ public static final int SCORE_FILTER_SCAN_RESULTS = 2;
/** @hide */
@IntDef({RECOMMENDATIONS_ENABLED_FORCED_OFF, RECOMMENDATIONS_ENABLED_OFF,
@@ -410,7 +409,7 @@
@RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
@Deprecated // migrate to registerNetworkScoreCache(int, INetworkScoreCache, int)
public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
- registerNetworkScoreCache(networkType, scoreCache, CACHE_FILTER_NONE);
+ registerNetworkScoreCache(networkType, scoreCache, SCORE_FILTER_NONE);
}
/**
@@ -418,7 +417,7 @@
*
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
* @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
- * @param filterType the {@link CacheUpdateFilter} to apply
+ * @param filterType the {@link ScoreUpdateFilter} to apply
* @throws SecurityException if the caller does not hold the
* {@link permission#REQUEST_NETWORK_SCORES} permission.
* @throws IllegalArgumentException if a score cache is already registered for this type.
@@ -426,7 +425,7 @@
*/
@RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache,
- @CacheUpdateFilter int filterType) {
+ @ScoreUpdateFilter int filterType) {
try {
mService.registerNetworkScoreCache(networkType, scoreCache, filterType);
} catch (RemoteException e) {
@@ -510,7 +509,7 @@
* Register a network score callback.
*
* @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
- * @param filterType the {@link CacheUpdateFilter} to apply
+ * @param filterType the {@link ScoreUpdateFilter} to apply
* @param callback implementation of {@link NetworkScoreCallback} that will be invoked when the
* scores change.
* @param executor The executor on which to execute the callbacks.
@@ -522,7 +521,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
public void registerNetworkScoreCallback(@NetworkKey.NetworkType int networkType,
- @CacheUpdateFilter int filterType,
+ @ScoreUpdateFilter int filterType,
@NonNull @CallbackExecutor Executor executor,
@NonNull NetworkScoreCallback callback) throws SecurityException {
if (callback == null || executor == null) {
diff --git a/core/java/android/os/TimestampedValue.java b/core/java/android/os/TimestampedValue.java
index 348574e..f4c87ac 100644
--- a/core/java/android/os/TimestampedValue.java
+++ b/core/java/android/os/TimestampedValue.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import java.util.Objects;
@@ -35,19 +36,27 @@
* @param <T> the type of the value with an associated timestamp
* @hide
*/
+@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class TimestampedValue<T> implements Parcelable {
private final long mReferenceTimeMillis;
+ @Nullable
private final T mValue;
- public TimestampedValue(long referenceTimeMillis, T value) {
+ public TimestampedValue(long referenceTimeMillis, @Nullable T value) {
mReferenceTimeMillis = referenceTimeMillis;
mValue = value;
}
+ /** Returns the reference time value. See {@link TimestampedValue} for more information. */
public long getReferenceTimeMillis() {
return mReferenceTimeMillis;
}
+ /**
+ * Returns the value associated with the timestamp. See {@link TimestampedValue} for more
+ * information.
+ */
+ @Nullable
public T getValue() {
return mValue;
}
@@ -86,6 +95,8 @@
return one.mReferenceTimeMillis - two.mReferenceTimeMillis;
}
+ /** @hide */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final @NonNull Parcelable.Creator<TimestampedValue<?>> CREATOR =
new Parcelable.ClassLoaderCreator<TimestampedValue<?>>() {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 548b123..089122d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -523,7 +523,9 @@
* Input: The Intent's data URI specifies bootstrapping information for authenticating and
* provisioning the peer, and uses a "DPP" scheme. The URI should be attached to the intent
* using {@link Intent#setData(Uri)}. The calling app can obtain a DPP URI in any
- * way, e.g. by scanning a QR code or other out-of-band methods.
+ * way, e.g. by scanning a QR code or other out-of-band methods. The calling app may also
+ * attach the {@link #EXTRA_EASY_CONNECT_BAND_LIST} extra to provide information
+ * about the bands supported by the enrollee device.
* <p>
* Output: After calling {@link android.app.Activity#startActivityForResult}, the callback
* {@code onActivityResult} will have resultCode {@link android.app.Activity#RESULT_OK} if
@@ -595,17 +597,29 @@
/**
* Activity Extra: The Band List that the Enrollee supports.
* <p>
- * An extra returned on the result intent received when using the {@link
- * #ACTION_PROCESS_WIFI_EASY_CONNECT_URI} intent to launch the Easy Connect Operation. This
- * extra contains the bands the Enrollee supports, expressed as the Global Operating Class,
- * see Table E-4 in IEEE Std 802.11-2016 Global operating classes. This value is populated only
- * by remote R2 devices, and only for the following error codes: {@link
- * android.net.wifi.EasyConnectStatusCallback#EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK}
- * {@link android.net.wifi.EasyConnectStatusCallback#EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION}
+ * This extra contains the bands the Enrollee supports, expressed as the Global Operating
+ * Class, see Table E-4 in IEEE Std 802.11-2016 Global operating classes. It is used both as
+ * input, to configure the Easy Connect operation and as output of the operation.
+ * <p>
+ * As input: an optional extra to be attached to the
+ * {@link #ACTION_PROCESS_WIFI_EASY_CONNECT_URI}. If attached, it indicates the bands which
+ * the remote device (enrollee, device-to-be-configured) supports. The Settings operation
+ * may take this into account when presenting the user with list of networks configurations
+ * to be used. The calling app may obtain this information in any out-of-band method. The
+ * information should be attached as an array of raw integers - using the
+ * {@link Intent#putExtra(String, int[])}.
+ * <p>
+ * As output: an extra returned on the result intent received when using the
+ * {@link #ACTION_PROCESS_WIFI_EASY_CONNECT_URI} intent to launch the Easy Connect Operation
+ * . This value is populated only by remote R2 devices, and only for the following error
+ * codes:
+ * {@link android.net.wifi.EasyConnectStatusCallback#EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK},
+ * {@link android.net.wifi.EasyConnectStatusCallback#EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION},
+ * or
* {@link android.net.wifi.EasyConnectStatusCallback#EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION}.
- * Therefore, always check if this extra is available using {@link Intent#hasExtra(String)}. If
- * there is no error, i.e. if the operation returns {@link android.app.Activity#RESULT_OK}, then
- * this extra is not attached to the result intent.
+ * Therefore, always check if this extra is available using {@link Intent#hasExtra(String)}.
+ * If there is no error, i.e. if the operation returns {@link android.app.Activity#RESULT_OK}
+ * , then this extra is not attached to the result intent.
* <p>
* Use the {@link Intent#getIntArrayExtra(String)} to obtain the list.
*/
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ca8ba4c..e0f6e06 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -826,6 +826,10 @@
if (mWindowAttributes.packageName == null) {
mWindowAttributes.packageName = mBasePackageName;
}
+ if (WindowManagerGlobal.USE_BLAST_ADAPTER) {
+ mWindowAttributes.privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST;
+ }
attrs = mWindowAttributes;
setTag();
@@ -1308,7 +1312,7 @@
mWindowAttributes.privateFlags |= compatibleWindowFlag;
if (WindowManagerGlobal.USE_BLAST_ADAPTER) {
- mWindowAttributes.privateFlags =
+ mWindowAttributes.privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST;
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 20af76b..f851e10 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -5737,7 +5737,7 @@
private boolean mIsDraggingCursor;
public void onTouchEvent(MotionEvent event) {
- if (getSelectionController().isCursorBeingModified()) {
+ if (hasSelectionController() && getSelectionController().isCursorBeingModified()) {
return;
}
switch (event.getActionMasked()) {
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index 13bfc1b..31b5e49 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -44,21 +44,21 @@
import com.android.internal.util.XmlUtils;
import com.android.server.DropboxLogTags;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.FileNotFoundException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
/**
* Performs a number of miscellaneous, non-system-critical actions
* after the system has finished booting.
@@ -424,7 +424,23 @@
for (String propPostfix : MOUNT_DURATION_PROPS_POSTFIX) {
int duration = SystemProperties.getInt("ro.boottime.init.mount_all." + propPostfix, 0);
if (duration != 0) {
- MetricsLogger.histogram(null, "boot_mount_all_duration_" + propPostfix, duration);
+ int eventType;
+ switch (propPostfix) {
+ case "early":
+ eventType = StatsLog.BOOT_TIME_EVENT_DURATION__EVENT__MOUNT_EARLY_DURATION;
+ break;
+ case "default":
+ eventType =
+ StatsLog.BOOT_TIME_EVENT_DURATION__EVENT__MOUNT_DEFAULT_DURATION;
+ break;
+ case "late":
+ eventType = StatsLog.BOOT_TIME_EVENT_DURATION__EVENT__MOUNT_LATE_DURATION;
+ break;
+ default:
+ continue;
+ }
+ StatsLog.write(StatsLog.BOOT_TIME_EVENT_DURATION_REPORTED, eventType,
+ duration);
}
}
}
@@ -555,16 +571,19 @@
Pattern pattern = Pattern.compile(LAST_SHUTDOWN_TIME_PATTERN, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(lines);
if (matcher.find()) {
- MetricsLogger.histogram(null, "boot_fs_shutdown_duration",
+ StatsLog.write(StatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,
+ StatsLog.BOOT_TIME_EVENT_DURATION__EVENT__SHUTDOWN_DURATION,
Integer.parseInt(matcher.group(1)));
- MetricsLogger.histogram(null, "boot_fs_shutdown_umount_stat",
+ StatsLog.write(StatsLog.BOOT_TIME_EVENT_ERROR_CODE_REPORTED,
+ StatsLog.BOOT_TIME_EVENT_ERROR_CODE__EVENT__SHUTDOWN_UMOUNT_STAT,
Integer.parseInt(matcher.group(2)));
Slog.i(TAG, "boot_fs_shutdown," + matcher.group(1) + "," + matcher.group(2));
} else { // not found
// This can happen when a device has too much kernel log after file system unmount
// ,exceeding maxReadSize. And having that much kernel logging can affect overall
// performance as well. So it is better to fix the kernel to reduce the amount of log.
- MetricsLogger.histogram(null, "boot_fs_shutdown_umount_stat",
+ StatsLog.write(StatsLog.BOOT_TIME_EVENT_ERROR_CODE_REPORTED,
+ StatsLog.BOOT_TIME_EVENT_ERROR_CODE__EVENT__SHUTDOWN_UMOUNT_STAT,
UMOUNT_STATUS_NOT_AVAILABLE);
Slog.w(TAG, "boot_fs_shutdown, string not found");
}
@@ -674,7 +693,11 @@
return;
}
stat = fixFsckFsStat(partition, stat, lines, startLineNumber, endLineNumber);
- MetricsLogger.histogram(null, "boot_fs_stat_" + partition, stat);
+ if ("userdata".equals(partition) || "data".equals(partition)) {
+ StatsLog.write(StatsLog.BOOT_TIME_EVENT_ERROR_CODE_REPORTED,
+ StatsLog.BOOT_TIME_EVENT_ERROR_CODE__EVENT__FS_MGR_FS_STAT_DATA_PARTITION,
+ stat);
+ }
Slog.i(TAG, "fs_stat, partition:" + partition + " stat:0x" + Integer.toHexString(stat));
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 6e6746f..a2f514a 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -344,7 +344,6 @@
cppflags: ["-Wno-conversion-null"],
srcs: [
- "android/graphics/apex/android_bitmap.cpp",
"android/graphics/apex/android_matrix.cpp",
"android/graphics/apex/android_paint.cpp",
"android/graphics/apex/android_region.cpp",
@@ -430,6 +429,7 @@
android: {
srcs: [ // sources that depend on android only libraries
"android/graphics/apex/android_canvas.cpp",
+ "android/graphics/apex/android_bitmap.cpp",
"android/graphics/apex/renderthread.cpp",
"android/graphics/apex/jni_runtime.cpp",
diff --git a/core/jni/android/graphics/apex/android_bitmap.cpp b/core/jni/android/graphics/apex/android_bitmap.cpp
index 90cc986..6a3c01e 100644
--- a/core/jni/android/graphics/apex/android_bitmap.cpp
+++ b/core/jni/android/graphics/apex/android_bitmap.cpp
@@ -122,6 +122,98 @@
return getInfo(bitmap->info(), bitmap->rowBytes());
}
+static bool nearlyEqual(float a, float b) {
+ // By trial and error, this is close enough to match for the ADataSpaces we
+ // compare for.
+ return ::fabs(a - b) < .002f;
+}
+
+static bool nearlyEqual(const skcms_TransferFunction& x, const skcms_TransferFunction& y) {
+ return nearlyEqual(x.g, y.g)
+ && nearlyEqual(x.a, y.a)
+ && nearlyEqual(x.b, y.b)
+ && nearlyEqual(x.c, y.c)
+ && nearlyEqual(x.d, y.d)
+ && nearlyEqual(x.e, y.e)
+ && nearlyEqual(x.f, y.f);
+}
+
+static bool nearlyEqual(const skcms_Matrix3x3& x, const skcms_Matrix3x3& y) {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ if (!nearlyEqual(x.vals[i][j], y.vals[i][j])) return false;
+ }
+ }
+ return true;
+}
+
+static constexpr skcms_TransferFunction k2Dot6 = {2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+
+// Skia's SkNamedGamut::kDCIP3 is based on a white point of D65. This gamut
+// matches the white point used by ColorSpace.Named.DCIP3.
+static constexpr skcms_Matrix3x3 kDCIP3 = {{
+ {0.486143, 0.323835, 0.154234},
+ {0.226676, 0.710327, 0.0629966},
+ {0.000800549, 0.0432385, 0.78275},
+}};
+
+ADataSpace ABitmap_getDataSpace(ABitmap* bitmapHandle) {
+ Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
+ const SkImageInfo& info = bitmap->info();
+ SkColorSpace* colorSpace = info.colorSpace();
+ if (!colorSpace) {
+ return ADATASPACE_UNKNOWN;
+ }
+
+ if (colorSpace->isSRGB()) {
+ if (info.colorType() == kRGBA_F16_SkColorType) {
+ return ADATASPACE_SCRGB;
+ }
+ return ADATASPACE_SRGB;
+ }
+
+ skcms_TransferFunction fn;
+ LOG_ALWAYS_FATAL_IF(!colorSpace->isNumericalTransferFn(&fn));
+
+ skcms_Matrix3x3 gamut;
+ LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&gamut));
+
+ if (nearlyEqual(gamut, SkNamedGamut::kSRGB)) {
+ if (nearlyEqual(fn, SkNamedTransferFn::kLinear)) {
+ // Skia doesn't differentiate amongst the RANGES. In Java, we associate
+ // LINEAR_EXTENDED_SRGB with F16, and LINEAR_SRGB with other Configs.
+ // Make the same association here.
+ if (info.colorType() == kRGBA_F16_SkColorType) {
+ return ADATASPACE_SCRGB_LINEAR;
+ }
+ return ADATASPACE_SRGB_LINEAR;
+ }
+
+ if (nearlyEqual(fn, SkNamedTransferFn::kRec2020)) {
+ return ADATASPACE_BT709;
+ }
+ }
+
+ if (nearlyEqual(fn, SkNamedTransferFn::kSRGB) && nearlyEqual(gamut, SkNamedGamut::kDCIP3)) {
+ return ADATASPACE_DISPLAY_P3;
+ }
+
+ if (nearlyEqual(fn, SkNamedTransferFn::k2Dot2) && nearlyEqual(gamut, SkNamedGamut::kAdobeRGB)) {
+ return ADATASPACE_ADOBE_RGB;
+ }
+
+ if (nearlyEqual(fn, SkNamedTransferFn::kRec2020) &&
+ nearlyEqual(gamut, SkNamedGamut::kRec2020)) {
+ return ADATASPACE_BT2020;
+ }
+
+ if (nearlyEqual(fn, k2Dot6) && nearlyEqual(gamut, kDCIP3)) {
+ return ADATASPACE_DCI_P3;
+ }
+
+ return ADATASPACE_UNKNOWN;
+}
+
AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj) {
uint32_t rowBytes = 0;
SkImageInfo imageInfo = GraphicsJNI::getBitmapInfo(env, bitmapObj, &rowBytes);
diff --git a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
index f231eed..32b8a45 100644
--- a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
+++ b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
@@ -17,6 +17,7 @@
#define ANDROID_GRAPHICS_BITMAP_H
#include <android/bitmap.h>
+#include <android/data_space.h>
#include <jni.h>
#include <sys/cdefs.h>
@@ -49,6 +50,7 @@
void ABitmap_releaseRef(ABitmap* bitmap);
AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmap);
+ADataSpace ABitmap_getDataSpace(ABitmap* bitmap);
void* ABitmap_getPixels(ABitmap* bitmap);
void ABitmap_notifyPixelsChanged(ABitmap* bitmap);
@@ -106,6 +108,7 @@
ABitmap* get() const { return mBitmap; }
AndroidBitmapInfo getInfo() const { return ABitmap_getInfo(mBitmap); }
+ ADataSpace getDataSpace() const { return ABitmap_getDataSpace(mBitmap); }
void* getPixels() const { return ABitmap_getPixels(mBitmap); }
void notifyPixelsChanged() const { ABitmap_notifyPixelsChanged(mBitmap); }
@@ -119,4 +122,4 @@
}; // namespace android
#endif // __cplusplus
-#endif // ANDROID_GRAPHICS_BITMAP_H
\ No newline at end of file
+#endif // ANDROID_GRAPHICS_BITMAP_H
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 466544c..673772a 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1156,6 +1156,36 @@
createAndMountAppData(package_name, ce_data_path, mirrorCePath, actualCePath, fail_fn);
}
+// Relabel directory
+static void relabelDir(const char* path, security_context_t context, fail_fn_t fail_fn) {
+ if (setfilecon(path, context) != 0) {
+ fail_fn(CREATE_ERROR("Failed to setfilecon %s %s", path, strerror(errno)));
+ }
+}
+
+// Relabel all directories under a path non-recursively.
+static void relabelAllDirs(const char* path, security_context_t context, fail_fn_t fail_fn) {
+ DIR* dir = opendir(path);
+ if (dir == nullptr) {
+ fail_fn(CREATE_ERROR("Failed to opendir %s", path));
+ }
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue;
+ auto filePath = StringPrintf("%s/%s", path, ent->d_name);
+ if (ent->d_type == DT_DIR) {
+ relabelDir(filePath.c_str(), context, fail_fn);
+ } else if (ent->d_type == DT_LNK) {
+ if (lsetfilecon(filePath.c_str(), context) != 0) {
+ fail_fn(CREATE_ERROR("Failed to lsetfilecon %s %s", filePath.c_str(), strerror(errno)));
+ }
+ } else {
+ fail_fn(CREATE_ERROR("Unexpected type: %d %s", ent->d_type, filePath.c_str()));
+ }
+ }
+ closedir(dir);
+}
+
/**
* Make other apps data directory not visible in CE, DE storage.
*
@@ -1215,10 +1245,36 @@
snprintf(internalDePath, PATH_MAX, "/data/user_de");
snprintf(externalPrivateMountPath, PATH_MAX, "/mnt/expand");
+ security_context_t dataDataContext = nullptr;
+ if (getfilecon(internalDePath, &dataDataContext) < 0) {
+ fail_fn(CREATE_ERROR("Unable to getfilecon on %s %s", internalDePath,
+ strerror(errno)));
+ }
+
MountAppDataTmpFs(internalLegacyCePath, fail_fn);
MountAppDataTmpFs(internalCePath, fail_fn);
MountAppDataTmpFs(internalDePath, fail_fn);
- MountAppDataTmpFs(externalPrivateMountPath, fail_fn);
+
+ // Mount tmpfs on all external vols DE and CE storage
+ DIR* dir = opendir(externalPrivateMountPath);
+ if (dir == nullptr) {
+ fail_fn(CREATE_ERROR("Failed to opendir %s", externalPrivateMountPath));
+ }
+ struct dirent* ent;
+ while ((ent = readdir(dir))) {
+ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue;
+ if (ent->d_type != DT_DIR) {
+ fail_fn(CREATE_ERROR("Unexpected type: %d %s", ent->d_type, ent->d_name));
+ }
+ auto volPath = StringPrintf("%s/%s", externalPrivateMountPath, ent->d_name);
+ auto cePath = StringPrintf("%s/user", volPath.c_str());
+ auto dePath = StringPrintf("%s/user_de", volPath.c_str());
+ MountAppDataTmpFs(cePath.c_str(), fail_fn);
+ MountAppDataTmpFs(dePath.c_str(), fail_fn);
+ }
+ closedir(dir);
+
+ bool legacySymlinkCreated = false;
for (int i = 0; i < size; i += 3) {
jstring package_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i));
@@ -1266,7 +1322,14 @@
// If it's user 0, create a symlink /data/user/0 -> /data/data,
// otherwise create /data/user/$USER
if (userId == 0) {
- symlink(internalLegacyCePath, internalCeUserPath);
+ if (!legacySymlinkCreated) {
+ legacySymlinkCreated = true;
+ int result = symlink(internalLegacyCePath, internalCeUserPath);
+ if (result != 0) {
+ fail_fn(CREATE_ERROR("Failed to create symlink %s %s", internalCeUserPath,
+ strerror(errno)));
+ }
+ }
actualCePath = internalLegacyCePath;
} else {
PrepareDirIfNotPresent(internalCeUserPath, DEFAULT_DATA_DIR_PERMISSION,
@@ -1280,6 +1343,43 @@
isolateAppDataPerPackage(userId, packageName, volUuid, ceDataInode,
actualCePath, actualDePath, fail_fn);
}
+ // We set the label AFTER everything is done, as we are applying
+ // the file operations on tmpfs. If we set the label when we mount
+ // tmpfs, SELinux will not happy as we are changing system_data_files.
+ // Relabel dir under /data/user, including /data/user/0
+ relabelAllDirs(internalCePath, dataDataContext, fail_fn);
+
+ // Relabel /data/user
+ relabelDir(internalCePath, dataDataContext, fail_fn);
+
+ // Relabel /data/data
+ relabelDir(internalLegacyCePath, dataDataContext, fail_fn);
+
+ // Relabel dir under /data/user_de
+ relabelAllDirs(internalDePath, dataDataContext, fail_fn);
+
+ // Relabel /data/user_de
+ relabelDir(internalDePath, dataDataContext, fail_fn);
+
+ // Relabel CE and DE dirs under /mnt/expand
+ dir = opendir(externalPrivateMountPath);
+ if (dir == nullptr) {
+ fail_fn(CREATE_ERROR("Failed to opendir %s", externalPrivateMountPath));
+ }
+ while ((ent = readdir(dir))) {
+ if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue;
+ auto volPath = StringPrintf("%s/%s", externalPrivateMountPath, ent->d_name);
+ auto cePath = StringPrintf("%s/user", volPath.c_str());
+ auto dePath = StringPrintf("%s/user_de", volPath.c_str());
+
+ relabelAllDirs(cePath.c_str(), dataDataContext, fail_fn);
+ relabelDir(cePath.c_str(), dataDataContext, fail_fn);
+ relabelAllDirs(dePath.c_str(), dataDataContext, fail_fn);
+ relabelDir(dePath.c_str(), dataDataContext, fail_fn);
+ }
+ closedir(dir);
+
+ freecon(dataDataContext);
}
// Utility routine to specialize a zygote child process.
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 06040a5..b71e539 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -32,8 +32,8 @@
import "frameworks/base/core/proto/android/server/job/enums.proto";
import "frameworks/base/core/proto/android/server/statlogger.proto";
import "frameworks/base/core/proto/android/privacy.proto";
+import "frameworks/base/core/proto/android/util/quotatracker.proto";
-// Next tag: 21
message JobSchedulerServiceDumpProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -160,10 +160,13 @@
optional JobConcurrencyManagerProto concurrency_manager = 20;
optional JobStorePersistStatsProto persist_stats = 21;
+
+ optional .android.util.quota.CountQuotaTrackerProto quota_tracker = 22;
+
+ // Next tag: 23
}
// A com.android.server.job.JobSchedulerService.Constants object.
-// Next tag: 29
message ConstantsProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -246,6 +249,14 @@
// Whether to use heartbeats or rolling window for quota management. True
// will use heartbeats, false will use a rolling window.
reserved 23; // use_heartbeats
+ // Whether to enable quota limits on APIs.
+ optional bool enable_api_quotas = 31;
+ // The maximum number of schedule() calls an app can make in a set amount of time.
+ optional int32 api_quota_schedule_count = 32;
+ // The time window that {@link #API_QUOTA_SCHEDULE_COUNT} should be evaluated over.
+ optional int64 api_quota_schedule_window_ms = 33;
+ // Whether or not to throw an exception when an app hits its schedule quota limit.
+ optional bool api_quota_schedule_throw_exception = 34;
message QuotaController {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -331,7 +342,7 @@
// In this time after screen turns on, we increase job concurrency.
optional int32 screen_off_job_concurrency_increase_delay_ms = 28;
- // Next tag: 31
+ // Next tag: 35
}
// Next tag: 4
@@ -651,8 +662,7 @@
optional bool is_active = 2;
// The time this timer last became active. Only valid if is_active is true.
optional int64 start_time_elapsed = 3;
- // How many background jobs are currently running. Valid only if the device is_active
- // is true.
+ // How many background jobs are currently running. Valid only if is_active is true.
optional int32 bg_job_count = 4;
// All of the jobs that the Timer is currently tracking.
repeated JobStatusShortInfoProto running_jobs = 5;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b78b181..7ecd9b7 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2568,7 +2568,7 @@
<!-- Allows telephony to suggest the time / time zone.
<p>Not for use by third-party applications.
- @hide
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @hide
-->
<permission android:name="android.permission.SUGGEST_PHONE_TIME_AND_ZONE"
android:protectionLevel="signature|telephony" />
diff --git a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
index 89c2374..8c9b4d0 100644
--- a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
+++ b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
@@ -67,6 +67,7 @@
mOriginalFlagValue = Editor.FLAG_ENABLE_CURSOR_DRAG;
Editor.FLAG_ENABLE_CURSOR_DRAG = true;
}
+
@After
public void after() throws Throwable {
Editor.FLAG_ENABLE_CURSOR_DRAG = mOriginalFlagValue;
@@ -356,6 +357,23 @@
assertFalse(editor.getSelectionController().isCursorBeingModified());
}
+ @Test // Reproduces b/147366705
+ public void testCursorDrag_nonSelectableTextView() throws Throwable {
+ String text = "Hello world!";
+ TextView tv = mActivity.findViewById(R.id.nonselectable_textview);
+ tv.setText(text);
+ Editor editor = tv.getEditorForTesting();
+
+ // Simulate a tap. No error should be thrown.
+ long event1Time = 1001;
+ MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f);
+ mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event1));
+
+ // Swipe left to right. No error should be thrown.
+ onView(withId(R.id.nonselectable_textview)).perform(
+ dragOnText(text.indexOf("llo"), text.indexOf("!")));
+ }
+
private static MotionEvent downEvent(long downTime, long eventTime, float x, float y) {
return MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);
}
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
index b411668..aa55e08 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
@@ -19,7 +19,6 @@
import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemDisabled;
import static android.widget.espresso.ContextMenuUtils.assertContextMenuContainsItemEnabled;
import static android.widget.espresso.ContextMenuUtils.assertContextMenuIsNotDisplayed;
-import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles;
import static android.widget.espresso.DragHandleUtils.onHandleView;
import static android.widget.espresso.TextViewActions.mouseClick;
import static android.widget.espresso.TextViewActions.mouseClickOnTextAtIndex;
@@ -64,7 +63,6 @@
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
-@Suppress // Consistently failing. b/29591177
public class TextViewActivityMouseTest {
@Rule
@@ -86,11 +84,8 @@
onView(withId(R.id.textview)).perform(mouseClick());
onView(withId(R.id.textview)).perform(replaceText(helloWorld));
- assertNoSelectionHandles();
-
onView(withId(R.id.textview)).perform(
mouseDragOnText(helloWorld.indexOf("llo"), helloWorld.indexOf("ld!")));
-
onView(withId(R.id.textview)).check(hasSelection("llo wor"));
onHandleView(com.android.internal.R.id.selection_start_handle)
@@ -100,8 +95,6 @@
onView(withId(R.id.textview)).perform(mouseClickOnTextAtIndex(helloWorld.indexOf("w")));
onView(withId(R.id.textview)).check(hasSelection(""));
-
- assertNoSelectionHandles();
}
@Test
@@ -196,11 +189,11 @@
onView(withId(R.id.textview)).check(matches(withText("abc ghi.def")));
onView(withId(R.id.textview)).check(hasSelection(""));
- assertNoSelectionHandles();
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex("abc ghi.def".length()));
}
@Test
+ @Suppress // Consistently failing. b/29591177
public void testDragAndDrop_longClick() {
final String text = "abc def ghi.";
onView(withId(R.id.textview)).perform(mouseClick());
@@ -213,7 +206,6 @@
onView(withId(R.id.textview)).check(matches(withText("abc ghi.def")));
onView(withId(R.id.textview)).check(hasSelection(""));
- assertNoSelectionHandles();
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex("abc ghi.def".length()));
}
diff --git a/core/tests/coretests/src/android/widget/espresso/MouseUiController.java b/core/tests/coretests/src/android/widget/espresso/MouseUiController.java
index abee736..1928d25 100644
--- a/core/tests/coretests/src/android/widget/espresso/MouseUiController.java
+++ b/core/tests/coretests/src/android/widget/espresso/MouseUiController.java
@@ -70,6 +70,8 @@
event.setSource(InputDevice.SOURCE_MOUSE);
if (event.getActionMasked() != MotionEvent.ACTION_UP) {
event.setButtonState(mButton);
+ } else {
+ event.setButtonState(0);
}
return mUiController.injectMotionEvent(event);
}
diff --git a/media/java/android/media/IMediaRoute2ProviderClient.aidl b/media/java/android/media/IMediaRoute2ProviderClient.aidl
index e8abfdc..0fccb3a 100644
--- a/media/java/android/media/IMediaRoute2ProviderClient.aidl
+++ b/media/java/android/media/IMediaRoute2ProviderClient.aidl
@@ -25,8 +25,10 @@
* @hide
*/
oneway interface IMediaRoute2ProviderClient {
- void updateState(in MediaRoute2ProviderInfo providerInfo,
- in List<RoutingSessionInfo> sessionInfos);
- void notifySessionCreated(in @nullable RoutingSessionInfo sessionInfo, long requestId);
- void notifySessionInfoChanged(in RoutingSessionInfo sessionInfo);
+ // TODO: Change it to updateRoutes?
+ void updateState(in MediaRoute2ProviderInfo providerInfo);
+ void notifySessionCreated(in RoutingSessionInfo sessionInfo, long requestId);
+ void notifySessionCreationFailed(long requestId);
+ void notifySessionUpdated(in RoutingSessionInfo sessionInfo);
+ void notifySessionReleased(in RoutingSessionInfo sessionInfo);
}
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 1cd5dfa..6d9aea5 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -58,6 +58,16 @@
public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService";
+ /**
+ * The request ID to pass {@link #notifySessionCreated(RoutingSessionInfo, long)}
+ * when {@link MediaRoute2ProviderService} created a session although there was no creation
+ * request.
+ *
+ * @see #notifySessionCreated(RoutingSessionInfo, long)
+ * @hide
+ */
+ public static final long REQUEST_ID_UNKNOWN = 0;
+
private final Handler mHandler;
private final Object mSessionLock = new Object();
private final AtomicBoolean mStatePublishScheduled = new AtomicBoolean(false);
@@ -118,7 +128,7 @@
*
* @param sessionId id of the session
* @return information of the session with the given id.
- * null if the session is destroyed or id is not valid.
+ * null if the session is released or ID is not valid.
* @hide
*/
@Nullable
@@ -143,90 +153,39 @@
}
/**
- * Updates the information of a session.
- * If the session is destroyed or not created before, it will be ignored.
- * Call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify clients of
- * session info changes.
- *
- * @param sessionInfo new session information
- * @see #notifySessionCreated(RoutingSessionInfo, long)
- * @hide
- */
- public final void updateSessionInfo(@NonNull RoutingSessionInfo sessionInfo) {
- Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
- String sessionId = sessionInfo.getId();
-
- synchronized (mSessionLock) {
- if (mSessionInfo.containsKey(sessionId)) {
- mSessionInfo.put(sessionId, sessionInfo);
- schedulePublishState();
- } else {
- Log.w(TAG, "Ignoring unknown session info.");
- return;
- }
- }
- }
-
- /**
- * Notifies the session is changed.
- *
- * TODO: This method is temporary, only created for tests. Remove when the alternative is ready.
- * @hide
- */
- public final void notifySessionInfoChanged(@NonNull RoutingSessionInfo sessionInfo) {
- Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
-
- String sessionId = sessionInfo.getId();
- synchronized (mSessionLock) {
- if (mSessionInfo.containsKey(sessionId)) {
- mSessionInfo.put(sessionId, sessionInfo);
- } else {
- Log.w(TAG, "Ignoring unknown session info.");
- return;
- }
- }
-
- if (mClient == null) {
- return;
- }
- try {
- mClient.notifySessionInfoChanged(sessionInfo);
- } catch (RemoteException ex) {
- Log.w(TAG, "Failed to notify session info changed.");
- }
- }
-
- /**
- * Notifies clients of that the session is created and ready for use. If the session can be
- * controlled, pass a {@link Bundle} that contains how to control it.
+ * Notifies clients of that the session is created and ready for use.
+ * <p>
+ * If this session is created without any creation request, use {@link #REQUEST_ID_UNKNOWN}
+ * as the request ID.
*
* @param sessionInfo information of the new session.
- * The {@link RoutingSessionInfo#getId() id} of the session must be
- * unique. Pass {@code null} to reject the request or inform clients that
- * session creation is failed.
- * @param requestId id of the previous request to create this session
+ * The {@link RoutingSessionInfo#getId() id} of the session must be unique.
+ * @param requestId id of the previous request to create this session provided in
+ * {@link #onCreateSession(String, String, String, long)}
+ * @see #onCreateSession(String, String, String, long)
* @hide
*/
- // TODO: fail reason?
- // TODO: Maybe better to create notifySessionCreationFailed?
- public final void notifySessionCreated(@Nullable RoutingSessionInfo sessionInfo,
+ public final void notifySessionCreated(@NonNull RoutingSessionInfo sessionInfo,
long requestId) {
- if (sessionInfo != null) {
- String sessionId = sessionInfo.getId();
- synchronized (mSessionLock) {
- if (mSessionInfo.containsKey(sessionId)) {
- Log.w(TAG, "Ignoring duplicate session id.");
- return;
- }
- mSessionInfo.put(sessionInfo.getId(), sessionInfo);
+ Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+
+ String sessionId = sessionInfo.getId();
+ synchronized (mSessionLock) {
+ if (mSessionInfo.containsKey(sessionId)) {
+ Log.w(TAG, "Ignoring duplicate session id.");
+ return;
}
- schedulePublishState();
+ mSessionInfo.put(sessionInfo.getId(), sessionInfo);
}
+ schedulePublishState();
if (mClient == null) {
return;
}
try {
+ // TODO: Calling binder calls in multiple thread may cause timing issue.
+ // Consider to change implementations to avoid the problems.
+ // For example, post binder calls, always send all sessions at once, etc.
mClient.notifySessionCreated(sessionInfo, requestId);
} catch (RemoteException ex) {
Log.w(TAG, "Failed to notify session created.");
@@ -234,70 +193,138 @@
}
/**
- * Releases a session with the given id.
- * {@link #onDestroySession} is called if the session is released.
+ * Notifies clients of that the session could not be created.
*
- * @param sessionId id of the session to be released
- * @see #onDestroySession(String, RoutingSessionInfo)
+ * @param requestId id of the previous request to create the session provided in
+ * {@link #onCreateSession(String, String, String, long)}.
+ * @see #onCreateSession(String, String, String, long)
* @hide
*/
- public final void releaseSession(@NonNull String sessionId) {
- if (TextUtils.isEmpty(sessionId)) {
- throw new IllegalArgumentException("sessionId must not be empty");
+ public final void notifySessionCreationFailed(long requestId) {
+ if (mClient == null) {
+ return;
}
- //TODO: notify media router service of release.
- RoutingSessionInfo sessionInfo;
- synchronized (mSessionLock) {
- sessionInfo = mSessionInfo.remove(sessionId);
- }
- if (sessionInfo != null) {
- mHandler.sendMessage(obtainMessage(
- MediaRoute2ProviderService::onDestroySession, this, sessionId, sessionInfo));
- schedulePublishState();
+ try {
+ mClient.notifySessionCreationFailed(requestId);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Failed to notify session creation failed.");
}
}
/**
- * Called when a session should be created.
+ * Notifies the existing session is updated. For example, when
+ * {@link RoutingSessionInfo#getSelectedRoutes() selected routes} are changed.
+ *
+ * @hide
+ */
+ public final void notifySessionUpdated(@NonNull RoutingSessionInfo sessionInfo) {
+ Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+
+ String sessionId = sessionInfo.getId();
+ synchronized (mSessionLock) {
+ if (mSessionInfo.containsKey(sessionId)) {
+ mSessionInfo.put(sessionId, sessionInfo);
+ } else {
+ Log.w(TAG, "Ignoring unknown session info.");
+ return;
+ }
+ }
+
+ if (mClient == null) {
+ return;
+ }
+ try {
+ mClient.notifySessionUpdated(sessionInfo);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Failed to notify session info changed.");
+ }
+ }
+
+ /**
+ * Notifies that the session is released.
+ *
+ * @param sessionId id of the released session.
+ * @see #onReleaseSession(String)
+ * @hide
+ */
+ public final void notifySessionReleased(@NonNull String sessionId) {
+ if (TextUtils.isEmpty(sessionId)) {
+ throw new IllegalArgumentException("sessionId must not be empty");
+ }
+ RoutingSessionInfo sessionInfo;
+ synchronized (mSessionLock) {
+ sessionInfo = mSessionInfo.remove(sessionId);
+ }
+
+ if (sessionInfo == null) {
+ Log.w(TAG, "Ignoring unknown session info.");
+ return;
+ }
+
+ if (mClient == null) {
+ return;
+ }
+ try {
+ mClient.notifySessionReleased(sessionInfo);
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Failed to notify session info changed.");
+ }
+ }
+
+ /**
+ * Called when the service receives a request to create a session.
+ * <p>
* You should create and maintain your own session and notifies the client of
* session info. Call {@link #notifySessionCreated(RoutingSessionInfo, long)}
* with the given {@code requestId} to notify the information of a new session.
- * If you can't create the session or want to reject the request, pass {@code null}
- * as session info in {@link #notifySessionCreated(RoutingSessionInfo, long)}
- * with the given {@code requestId}.
+ * The created session must have the same route feature and must include the given route
+ * specified by {@code routeId}.
+ * <p>
+ * If the session can be controlled, you can optionally pass the control hints to
+ * {@link RoutingSessionInfo.Builder#setControlHints(Bundle)}. Control hints is a
+ * {@link Bundle} which contains how to control the session.
+ * <p>
+ * If you can't create the session or want to reject the request, call
+ * {@link #notifySessionCreationFailed(long)} with the given {@code requestId}.
*
* @param packageName the package name of the application that selected the route
* @param routeId the id of the route initially being connected
* @param routeFeature the route feature of the new session
* @param requestId the id of this session creation request
+ *
+ * @see RoutingSessionInfo.Builder#Builder(String, String, String)
+ * @see RoutingSessionInfo.Builder#addSelectedRoute(String)
+ * @see RoutingSessionInfo.Builder#setControlHints(Bundle)
* @hide
*/
public abstract void onCreateSession(@NonNull String packageName, @NonNull String routeId,
@NonNull String routeFeature, long requestId);
/**
- * Called when a session is about to be destroyed.
- * You can clean up your session here. This can happen by the
- * client or provider itself.
+ * Called when the session should be released. A client of the session or system can request
+ * a session to be released.
+ * <p>
+ * After releasing the session, call {@link #notifySessionReleased(String)}
+ * with the ID of the released session.
*
- * @param sessionId id of the session being destroyed.
- * @param lastSessionInfo information of the session being destroyed.
- * @see #releaseSession(String)
+ * Note: Calling {@link #notifySessionReleased(String)} will <em>NOT</em> trigger
+ * this method to be called.
+ *
+ * @param sessionId id of the session being released.
+ * @see #notifySessionReleased(String)
+ * @see #getSessionInfo(String)
* @hide
*/
- public abstract void onDestroySession(@NonNull String sessionId,
- @NonNull RoutingSessionInfo lastSessionInfo);
+ public abstract void onReleaseSession(@NonNull String sessionId);
//TODO: make a way to reject the request
/**
* Called when a client requests selecting a route for the session.
- * After the route is selected, call {@link #updateSessionInfo(RoutingSessionInfo)} to update
- * session info and call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify
- * clients of updated session info.
+ * After the route is selected, call {@link #notifySessionUpdated(RoutingSessionInfo)}
+ * to update session info.
*
* @param sessionId id of the session
* @param routeId id of the route
- * @see #updateSessionInfo(RoutingSessionInfo)
* @hide
*/
public abstract void onSelectRoute(@NonNull String sessionId, @NonNull String routeId);
@@ -305,9 +332,8 @@
//TODO: make a way to reject the request
/**
* Called when a client requests deselecting a route from the session.
- * After the route is deselected, call {@link #updateSessionInfo(RoutingSessionInfo)} to update
- * session info and call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify
- * clients of updated session info.
+ * After the route is deselected, call {@link #notifySessionUpdated(RoutingSessionInfo)}
+ * to update session info.
*
* @param sessionId id of the session
* @param routeId id of the route
@@ -318,9 +344,8 @@
//TODO: make a way to reject the request
/**
* Called when a client requests transferring a session to a route.
- * After the transfer is finished, call {@link #updateSessionInfo(RoutingSessionInfo)} to update
- * session info and call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify
- * clients of updated session info.
+ * After the transfer is finished, call {@link #notifySessionUpdated(RoutingSessionInfo)}
+ * to update session info.
*
* @param sessionId id of the session
* @param routeId id of the route
@@ -344,6 +369,8 @@
* </p>
*
* @param preference the new discovery preference
+ *
+ * TODO: This method needs tests.
*/
public void onDiscoveryPreferenceChanged(@NonNull RouteDiscoveryPreference preference) {}
@@ -383,7 +410,7 @@
sessionInfos = new ArrayList<>(mSessionInfo.values());
}
try {
- mClient.updateState(mProviderInfo, sessionInfos);
+ mClient.updateState(mProviderInfo);
} catch (RemoteException ex) {
Log.w(TAG, "Failed to send onProviderInfoUpdated");
}
@@ -415,6 +442,7 @@
MediaRoute2ProviderService.this, packageName, routeId, routeFeature,
requestId));
}
+
@Override
public void releaseSession(@NonNull String sessionId) {
if (!checkCallerisSystem()) {
@@ -424,7 +452,7 @@
Log.w(TAG, "releaseSession: Ignoring empty sessionId from system service.");
return;
}
- mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::releaseSession,
+ mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onReleaseSession,
MediaRoute2ProviderService.this, sessionId));
}
diff --git a/media/java/android/media/MediaTranscodeManager.java b/media/java/android/media/MediaTranscodeManager.java
new file mode 100644
index 0000000..2c431b9
--- /dev/null
+++ b/media/java/android/media/MediaTranscodeManager.java
@@ -0,0 +1,403 @@
+/*
+ * Copyright (C) 2019 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.media;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * MediaTranscodeManager provides an interface to the system's media transcode service.
+ * Transcode requests are put in a queue and processed in order. When a transcode operation is
+ * completed the caller is notified via its OnTranscodingFinishedListener. In the meantime the
+ * caller may use the returned TranscodingJob object to cancel or check the status of a specific
+ * transcode operation.
+ * The currently supported media types are video and still images.
+ *
+ * TODO(lnilsson): Add sample code when API is settled.
+ *
+ * @hide
+ */
+public final class MediaTranscodeManager {
+ private static final String TAG = "MediaTranscodeManager";
+
+ // Invalid ID passed from native means the request was never enqueued.
+ private static final long ID_INVALID = -1;
+
+ // Events passed from native.
+ private static final int EVENT_JOB_STARTED = 1;
+ private static final int EVENT_JOB_PROGRESSED = 2;
+ private static final int EVENT_JOB_FINISHED = 3;
+
+ @IntDef(prefix = { "EVENT_" }, value = {
+ EVENT_JOB_STARTED,
+ EVENT_JOB_PROGRESSED,
+ EVENT_JOB_FINISHED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Event {}
+
+ private static MediaTranscodeManager sMediaTranscodeManager;
+ private final ConcurrentMap<Long, TranscodingJob> mPendingTranscodingJobs =
+ new ConcurrentHashMap<>();
+ private final Context mContext;
+
+ /**
+ * Listener that gets notified when a transcoding operation has finished.
+ * This listener gets notified regardless of how the operation finished. It is up to the
+ * listener implementation to check the result and take appropriate action.
+ */
+ @FunctionalInterface
+ public interface OnTranscodingFinishedListener {
+ /**
+ * Called when the transcoding operation has finished. The receiver may use the
+ * TranscodingJob to check the result, i.e. whether the operation succeeded, was canceled or
+ * if an error occurred.
+ * @param transcodingJob The TranscodingJob instance for the finished transcoding operation.
+ */
+ void onTranscodingFinished(@NonNull TranscodingJob transcodingJob);
+ }
+
+ /**
+ * Class describing a transcode operation to be performed. The caller uses this class to
+ * configure a transcoding operation that can then be enqueued using MediaTranscodeManager.
+ */
+ public static final class TranscodingRequest {
+ private Uri mSrcUri;
+ private Uri mDstUri;
+ private MediaFormat mDstFormat;
+
+ private TranscodingRequest(Builder b) {
+ mSrcUri = b.mSrcUri;
+ mDstUri = b.mDstUri;
+ mDstFormat = b.mDstFormat;
+ }
+
+ /** TranscodingRequest builder class. */
+ public static class Builder {
+ private Uri mSrcUri;
+ private Uri mDstUri;
+ private MediaFormat mDstFormat;
+
+ /**
+ * Specifies the source media file.
+ * @param uri Content uri for the source media file.
+ * @return The builder instance.
+ */
+ public Builder setSourceUri(Uri uri) {
+ mSrcUri = uri;
+ return this;
+ }
+
+ /**
+ * Specifies the destination media file.
+ * @param uri Content uri for the destination media file.
+ * @return The builder instance.
+ */
+ public Builder setDestinationUri(Uri uri) {
+ mDstUri = uri;
+ return this;
+ }
+
+ /**
+ * Specifies the media format of the transcoded media file.
+ * @param dstFormat MediaFormat containing the desired destination format.
+ * @return The builder instance.
+ */
+ public Builder setDestinationFormat(MediaFormat dstFormat) {
+ mDstFormat = dstFormat;
+ return this;
+ }
+
+ /**
+ * Builds a new TranscodingRequest with the configuration set on this builder.
+ * @return A new TranscodingRequest.
+ */
+ public TranscodingRequest build() {
+ return new TranscodingRequest(this);
+ }
+ }
+ }
+
+ /**
+ * Handle to an enqueued transcoding operation. An instance of this class represents a single
+ * enqueued transcoding operation. The caller can use that instance to query the status or
+ * progress, and to get the result once the operation has completed.
+ */
+ public static final class TranscodingJob {
+ /** The job is enqueued but not yet running. */
+ public static final int STATUS_PENDING = 1;
+ /** The job is currently running. */
+ public static final int STATUS_RUNNING = 2;
+ /** The job is finished. */
+ public static final int STATUS_FINISHED = 3;
+
+ @IntDef(prefix = { "STATUS_" }, value = {
+ STATUS_PENDING,
+ STATUS_RUNNING,
+ STATUS_FINISHED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Status {}
+
+ /** The job does not have a result yet. */
+ public static final int RESULT_NONE = 1;
+ /** The job completed successfully. */
+ public static final int RESULT_SUCCESS = 2;
+ /** The job encountered an error while running. */
+ public static final int RESULT_ERROR = 3;
+ /** The job was canceled by the caller. */
+ public static final int RESULT_CANCELED = 4;
+
+ @IntDef(prefix = { "RESULT_" }, value = {
+ RESULT_NONE,
+ RESULT_SUCCESS,
+ RESULT_ERROR,
+ RESULT_CANCELED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Result {}
+
+ /** Listener that gets notified when the progress changes. */
+ @FunctionalInterface
+ public interface OnProgressChangedListener {
+
+ /**
+ * Called when the progress changes. The progress is between 0 and 1, where 0 means
+ * that the job has not yet started and 1 means that it has finished.
+ * @param progress The new progress.
+ */
+ void onProgressChanged(float progress);
+ }
+
+ private final Executor mExecutor;
+ private final OnTranscodingFinishedListener mListener;
+ private final ReentrantLock mStatusChangeLock = new ReentrantLock();
+ private Executor mProgressChangedExecutor;
+ private OnProgressChangedListener mProgressChangedListener;
+ private long mID;
+ private float mProgress = 0.0f;
+ private @Status int mStatus = STATUS_PENDING;
+ private @Result int mResult = RESULT_NONE;
+
+ private TranscodingJob(long id, @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnTranscodingFinishedListener listener) {
+ mID = id;
+ mExecutor = executor;
+ mListener = listener;
+ }
+
+ /**
+ * Set a progress listener.
+ * @param listener The progress listener.
+ */
+ public void setOnProgressChangedListener(@NonNull @CallbackExecutor Executor executor,
+ @Nullable OnProgressChangedListener listener) {
+ mProgressChangedExecutor = executor;
+ mProgressChangedListener = listener;
+ }
+
+ /**
+ * Cancels the transcoding job and notify the listener. If the job happened to finish before
+ * being canceled this call is effectively a no-op and will not update the result in that
+ * case.
+ */
+ public void cancel() {
+ setJobFinished(RESULT_CANCELED);
+ sMediaTranscodeManager.native_cancelTranscodingRequest(mID);
+ }
+
+ /**
+ * Gets the progress of the transcoding job. The progress is between 0 and 1, where 0 means
+ * that the job has not yet started and 1 means that it is finished.
+ * @return The progress.
+ */
+ public float getProgress() {
+ return mProgress;
+ }
+
+ /**
+ * Gets the status of the transcoding job.
+ * @return The status.
+ */
+ public @Status int getStatus() {
+ return mStatus;
+ }
+
+ /**
+ * Gets the result of the transcoding job.
+ * @return The result.
+ */
+ public @Result int getResult() {
+ return mResult;
+ }
+
+ private void setJobStarted() {
+ mStatus = STATUS_RUNNING;
+ }
+
+ private void setJobProgress(float newProgress) {
+ mProgress = newProgress;
+
+ // Notify listener.
+ OnProgressChangedListener onProgressChangedListener = mProgressChangedListener;
+ if (onProgressChangedListener != null) {
+ mProgressChangedExecutor.execute(
+ () -> onProgressChangedListener.onProgressChanged(mProgress));
+ }
+ }
+
+ private void setJobFinished(int result) {
+ boolean doNotifyListener = false;
+
+ // Prevent conflicting simultaneous status updates from native (finished) and from the
+ // caller (cancel).
+ try {
+ mStatusChangeLock.lock();
+ if (mStatus != STATUS_FINISHED) {
+ mStatus = STATUS_FINISHED;
+ mResult = result;
+ doNotifyListener = true;
+ }
+ } finally {
+ mStatusChangeLock.unlock();
+ }
+
+ if (doNotifyListener) {
+ mExecutor.execute(() -> mListener.onTranscodingFinished(this));
+ }
+ }
+
+ private void processJobEvent(@Event int event, int arg) {
+ switch (event) {
+ case EVENT_JOB_STARTED:
+ setJobStarted();
+ break;
+ case EVENT_JOB_PROGRESSED:
+ setJobProgress((float) arg / 100);
+ break;
+ case EVENT_JOB_FINISHED:
+ setJobFinished(arg);
+ break;
+ default:
+ Log.e(TAG, "Unsupported event: " + event);
+ break;
+ }
+ }
+ }
+
+ // Initializes the native library.
+ private static native void native_init();
+ // Requests a new job ID from the native service.
+ private native long native_requestUniqueJobID();
+ // Enqueues a transcoding request to the native service.
+ private native boolean native_enqueueTranscodingRequest(
+ long id, @NonNull TranscodingRequest transcodingRequest, @NonNull Context context);
+ // Cancels an enqueued transcoding request.
+ private native void native_cancelTranscodingRequest(long id);
+
+ // Private constructor.
+ private MediaTranscodeManager(@NonNull Context context) {
+ mContext = context;
+ }
+
+ // Events posted from the native service.
+ @SuppressWarnings("unused")
+ private void postEventFromNative(@Event int event, long id, int arg) {
+ Log.d(TAG, String.format("postEventFromNative. Event %d, ID %d, arg %d", event, id, arg));
+
+ TranscodingJob transcodingJob = mPendingTranscodingJobs.get(id);
+
+ // Job IDs are added to the tracking set before the job is enqueued so it should never
+ // be null unless the service misbehaves.
+ if (transcodingJob == null) {
+ Log.e(TAG, "No matching transcode job found for id " + id);
+ return;
+ }
+
+ transcodingJob.processJobEvent(event, arg);
+ }
+
+ /**
+ * Gets the MediaTranscodeManager singleton instance.
+ * @param context The application context.
+ * @return the {@link MediaTranscodeManager} singleton instance.
+ */
+ public static MediaTranscodeManager getInstance(@NonNull Context context) {
+ Preconditions.checkNotNull(context);
+ synchronized (MediaTranscodeManager.class) {
+ if (sMediaTranscodeManager == null) {
+ sMediaTranscodeManager = new MediaTranscodeManager(context.getApplicationContext());
+ }
+ return sMediaTranscodeManager;
+ }
+ }
+
+ /**
+ * Enqueues a TranscodingRequest for execution.
+ * @param transcodingRequest The TranscodingRequest to enqueue.
+ * @param listenerExecutor Executor on which the listener is notified.
+ * @param listener Listener to get notified when the transcoding job is finished.
+ * @return A TranscodingJob for this operation.
+ */
+ public @Nullable TranscodingJob enqueueTranscodingRequest(
+ @NonNull TranscodingRequest transcodingRequest,
+ @NonNull @CallbackExecutor Executor listenerExecutor,
+ @NonNull OnTranscodingFinishedListener listener) {
+ Log.i(TAG, "enqueueTranscodingRequest called.");
+ Preconditions.checkNotNull(transcodingRequest);
+ Preconditions.checkNotNull(listenerExecutor);
+ Preconditions.checkNotNull(listener);
+
+ // Reserve a job ID.
+ long jobID = native_requestUniqueJobID();
+ if (jobID == ID_INVALID) {
+ return null;
+ }
+
+ // Add the job to the tracking set.
+ TranscodingJob transcodingJob = new TranscodingJob(jobID, listenerExecutor, listener);
+ mPendingTranscodingJobs.put(jobID, transcodingJob);
+
+ // Enqueue the request with the native service.
+ boolean enqueued = native_enqueueTranscodingRequest(jobID, transcodingRequest, mContext);
+ if (!enqueued) {
+ mPendingTranscodingJobs.remove(jobID);
+ return null;
+ }
+
+ return transcodingJob;
+ }
+
+ static {
+ System.loadLibrary("media_jni");
+ native_init();
+ }
+}
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 01f1250..27f02fe 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -719,9 +719,14 @@
if (track == null) {
break;
}
- // TODO: add synchronous versions
- track.stop();
- track.flush();
+ try {
+ // TODO: add synchronous versions
+ track.stop();
+ track.flush();
+ } catch (IllegalStateException e) {
+ // ignore exception, AudioTrack could have already been stopped or
+ // released by the user of the AudioPolicy
+ }
}
}
if (mCaptors != null) {
@@ -730,8 +735,13 @@
if (record == null) {
break;
}
- // TODO: if needed: implement an invalidate method
- record.stop();
+ try {
+ // TODO: if needed: implement an invalidate method
+ record.stop();
+ } catch (IllegalStateException e) {
+ // ignore exception, AudioRecord could have already been stopped or
+ // released by the user of the AudioPolicy
+ }
}
}
}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 862489f..e3dfaeb 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -16,6 +16,7 @@
package android.media.tv.tuner;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -32,11 +33,13 @@
import android.media.tv.tuner.frontend.FrontendCallback;
import android.media.tv.tuner.frontend.FrontendInfo;
import android.media.tv.tuner.frontend.FrontendStatus;
+import android.media.tv.tuner.frontend.ScanCallback;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* This class is used to interact with hardware tuners devices.
@@ -70,6 +73,10 @@
private List<Integer> mLnbIds;
private Lnb mLnb;
+ @Nullable
+ private ScanCallback mScanCallback;
+ @Nullable
+ private Executor mScanCallbackExecutor;
/**
* Constructs a Tuner instance.
@@ -231,29 +238,6 @@
private Frontend(int id) {
mId = id;
}
-
- public void setCallback(@Nullable FrontendCallback callback, @Nullable Handler handler) {
- mCallback = callback;
-
- if (mCallback == null) {
- return;
- }
-
- if (handler == null) {
- // use default looper if handler is null
- if (mHandler == null) {
- mHandler = createEventHandler();
- }
- return;
- }
-
- Looper looper = handler.getLooper();
- if (mHandler != null && mHandler.getLooper() == looper) {
- // the same looper. reuse mHandler
- return;
- }
- mHandler = new EventHandler(looper);
- }
}
/**
@@ -286,18 +270,32 @@
* Scan channels.
* @hide
*/
- public int scan(@NonNull FrontendSettings settings, @FrontendScanType int scanType) {
+ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
+ public int scan(@NonNull FrontendSettings settings, @FrontendScanType int scanType,
+ @NonNull @CallbackExecutor Executor executor, @NonNull ScanCallback scanCallback) {
+ mScanCallback = scanCallback;
+ mScanCallbackExecutor = executor;
return nativeScan(settings.getType(), settings, scanType);
}
/**
* Stops a previous scanning.
*
- * If the method completes successfully, the frontend stop previous scanning.
+ * <p>
+ * The {@link ScanCallback} and it's {@link Executor} will be removed.
+ *
+ * <p>
+ * If the method completes successfully, the frontend stopped previous scanning.
+ *
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public int stopScan() {
- return nativeStopScan();
+ TunerUtils.checkTunerPermission(mContext);
+ int retVal = nativeStopScan();
+ mScanCallback = null;
+ mScanCallbackExecutor = null;
+ return retVal;
}
/**
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
index c2d6c58c..4532122 100644
--- a/media/java/android/media/tv/tuner/TunerConstants.java
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -1015,10 +1015,13 @@
Constants.FrontendAtsc3DemodOutputFormat.BASEBAND_PACKET;
/** @hide */
- @IntDef({FRONTEND_DVBS_STANDARD_AUTO, FRONTEND_DVBS_STANDARD_S, FRONTEND_DVBS_STANDARD_S2,
- FRONTEND_DVBS_STANDARD_S2X})
+ @IntDef(prefix = "FRONTEND_DVBS_STANDARD",
+ value = {FRONTEND_DVBS_STANDARD_AUTO, FRONTEND_DVBS_STANDARD_S,
+ FRONTEND_DVBS_STANDARD_S2,
+ FRONTEND_DVBS_STANDARD_S2X})
@Retention(RetentionPolicy.SOURCE)
- public @interface FrontendDvbsStandard {}
+ public @interface FrontendDvbsStandard {
+ }
/** @hide */
public static final int FRONTEND_DVBS_STANDARD_AUTO = Constants.FrontendDvbsStandard.AUTO;
/** @hide */
@@ -1210,6 +1213,20 @@
Constants.FrontendDvbtGuardInterval.INTERVAL_19_256;
/** @hide */
+ @IntDef(prefix = "FRONTEND_DVBT_STANDARD",
+ value = {FRONTEND_DVBT_STANDARD_AUTO, FRONTEND_DVBT_STANDARD_T,
+ FRONTEND_DVBT_STANDARD_T2}
+ )
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FrontendDvbtStandard {}
+ /** @hide */
+ public static final int FRONTEND_DVBT_STANDARD_AUTO = Constants.FrontendDvbtStandard.AUTO;
+ /** @hide */
+ public static final int FRONTEND_DVBT_STANDARD_T = Constants.FrontendDvbtStandard.T;
+ /** @hide */
+ public static final int FRONTEND_DVBT_STANDARD_T2 = Constants.FrontendDvbtStandard.T2;
+
+ /** @hide */
@IntDef({FRONTEND_ISDBS_CODERATE_UNDEFINED, FRONTEND_ISDBS_CODERATE_AUTO,
FRONTEND_ISDBS_CODERATE_1_2, FRONTEND_ISDBS_CODERATE_2_3, FRONTEND_ISDBS_CODERATE_3_4,
FRONTEND_ISDBS_CODERATE_5_6, FRONTEND_ISDBS_CODERATE_7_8})
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendCallback.java b/media/java/android/media/tv/tuner/frontend/FrontendCallback.java
index 0992eb6..9c4f460 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendCallback.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendCallback.java
@@ -27,10 +27,4 @@
* Invoked when there is a frontend event.
*/
void onEvent(int frontendEventType);
-
- /**
- * Invoked when there is a scan message.
- * @param msg
- */
- void onScanMessage(ScanMessage msg);
}
diff --git a/media/java/android/media/tv/tuner/frontend/ScanCallback.java b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
new file mode 100644
index 0000000..8118fcc
--- /dev/null
+++ b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
@@ -0,0 +1,80 @@
+/*
+ * 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.media.tv.tuner.frontend;
+
+import android.media.tv.tuner.TunerConstants;
+
+/**
+ * Scan callback.
+ *
+ * @hide
+ */
+public interface ScanCallback {
+ /** Scan locked the signal. */
+ void onLocked(boolean isLocked);
+
+ /** Scan stopped. */
+ void onEnd(boolean isEnd);
+
+ /** scan progress percent (0..100) */
+ void onProgress(int percent);
+
+ /** Signal frequency in Hertz */
+ void onFrequencyReport(int frequency);
+
+ /** Symbols per second */
+ void onSymbolRate(int rate);
+
+ /** Locked Plp Ids for DVBT2 frontend. */
+ void onPlpIds(int[] plpIds);
+
+ /** Locked group Ids for DVBT2 frontend. */
+ void onGroupIds(int[] groupIds);
+
+ /** Stream Ids. */
+ void onInputStreamIds(int[] inputStreamIds);
+
+ /** Locked signal standard. */
+ void onDvbsStandard(@TunerConstants.FrontendDvbsStandard int dvbsStandandard);
+
+ /** Locked signal standard. */
+ void onDvbtStandard(@TunerConstants.FrontendDvbtStandard int dvbtStandard);
+
+ /** PLP status in a tuned frequency band for ATSC3 frontend. */
+ void onAtsc3PlpInfos(Atsc3PlpInfo[] atsc3PlpInfos);
+
+ /** PLP information for ATSC3. */
+ class Atsc3PlpInfo {
+ private final int mPlpId;
+ private final boolean mLlsFlag;
+
+ private Atsc3PlpInfo(int plpId, boolean llsFlag) {
+ mPlpId = plpId;
+ mLlsFlag = llsFlag;
+ }
+
+ /** Gets PLP IDs. */
+ public int getPlpId() {
+ return mPlpId;
+ }
+
+ /** Gets LLS flag. */
+ public boolean getLlsFlag() {
+ return mLlsFlag;
+ }
+ }
+}
diff --git a/media/java/android/media/tv/tuner/frontend/ScanMessage.java b/media/java/android/media/tv/tuner/frontend/ScanMessage.java
deleted file mode 100644
index dd687dd..0000000
--- a/media/java/android/media/tv/tuner/frontend/ScanMessage.java
+++ /dev/null
@@ -1,172 +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 android.media.tv.tuner.frontend;
-
-import android.annotation.IntDef;
-import android.hardware.tv.tuner.V1_0.Constants;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Message from frontend during scan operations.
- *
- * @hide
- */
-public class ScanMessage {
-
- /** @hide */
- @IntDef({
- LOCKED,
- END,
- PROGRESS_PERCENT,
- FREQUENCY,
- SYMBOL_RATE,
- PLP_IDS,
- GROUP_IDS,
- INPUT_STREAM_IDS,
- STANDARD,
- ATSC3_PLP_INFO
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
- /** @hide */
- public static final int LOCKED = Constants.FrontendScanMessageType.LOCKED;
- /** @hide */
- public static final int END = Constants.FrontendScanMessageType.END;
- /** @hide */
- public static final int PROGRESS_PERCENT = Constants.FrontendScanMessageType.PROGRESS_PERCENT;
- /** @hide */
- public static final int FREQUENCY = Constants.FrontendScanMessageType.FREQUENCY;
- /** @hide */
- public static final int SYMBOL_RATE = Constants.FrontendScanMessageType.SYMBOL_RATE;
- /** @hide */
- public static final int PLP_IDS = Constants.FrontendScanMessageType.PLP_IDS;
- /** @hide */
- public static final int GROUP_IDS = Constants.FrontendScanMessageType.GROUP_IDS;
- /** @hide */
- public static final int INPUT_STREAM_IDS = Constants.FrontendScanMessageType.INPUT_STREAM_IDS;
- /** @hide */
- public static final int STANDARD = Constants.FrontendScanMessageType.STANDARD;
- /** @hide */
- public static final int ATSC3_PLP_INFO = Constants.FrontendScanMessageType.ATSC3_PLP_INFO;
-
- private final int mType;
- private final Object mValue;
-
- private ScanMessage(int type, Object value) {
- mType = type;
- mValue = value;
- }
-
- /** Gets scan message type. */
- @Type
- public int getMessageType() {
- return mType;
- }
- /** Message indicates whether frontend is locked or not. */
- public boolean getIsLocked() {
- if (mType != LOCKED) {
- throw new IllegalStateException();
- }
- return (Boolean) mValue;
- }
- /** Message indicates whether the scan has reached the end or not. */
- public boolean getIsEnd() {
- if (mType != END) {
- throw new IllegalStateException();
- }
- return (Boolean) mValue;
- }
- /** Progress message in percent. */
- public int getProgressPercent() {
- if (mType != PROGRESS_PERCENT) {
- throw new IllegalStateException();
- }
- return (Integer) mValue;
- }
- /** Gets frequency. */
- public int getFrequency() {
- if (mType != FREQUENCY) {
- throw new IllegalStateException();
- }
- return (Integer) mValue;
- }
- /** Gets symbol rate. */
- public int getSymbolRate() {
- if (mType != SYMBOL_RATE) {
- throw new IllegalStateException();
- }
- return (Integer) mValue;
- }
- /** Gets PLP IDs. */
- public int[] getPlpIds() {
- if (mType != PLP_IDS) {
- throw new IllegalStateException();
- }
- return (int[]) mValue;
- }
- /** Gets group IDs. */
- public int[] getGroupIds() {
- if (mType != GROUP_IDS) {
- throw new IllegalStateException();
- }
- return (int[]) mValue;
- }
- /** Gets Input stream IDs. */
- public int[] getInputStreamIds() {
- if (mType != INPUT_STREAM_IDS) {
- throw new IllegalStateException();
- }
- return (int[]) mValue;
- }
- /** Gets the DVB-T or DVB-S standard. */
- public int getStandard() {
- if (mType != STANDARD) {
- throw new IllegalStateException();
- }
- return (int) mValue;
- }
-
- /** Gets PLP information for ATSC3. */
- public Atsc3PlpInfo[] getAtsc3PlpInfos() {
- if (mType != ATSC3_PLP_INFO) {
- throw new IllegalStateException();
- }
- return (Atsc3PlpInfo[]) mValue;
- }
-
- /** PLP information for ATSC3. */
- public static class Atsc3PlpInfo {
- private final int mPlpId;
- private final boolean mLlsFlag;
-
- private Atsc3PlpInfo(int plpId, boolean llsFlag) {
- mPlpId = plpId;
- mLlsFlag = llsFlag;
- }
-
- /** Gets PLP IDs. */
- public int getPlpId() {
- return mPlpId;
- }
- /** Gets LLS flag. */
- public boolean getLlsFlag() {
- return mLlsFlag;
- }
- }
-}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 536a061..aeacd8f 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -19,6 +19,7 @@
"android_media_MediaProfiles.cpp",
"android_media_MediaRecorder.cpp",
"android_media_MediaSync.cpp",
+ "android_media_MediaTranscodeManager.cpp",
"android_media_ResampleInputStream.cpp",
"android_media_Streams.cpp",
"android_media_SyncParams.cpp",
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 963b650..5cb42a9a 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1453,6 +1453,7 @@
extern int register_android_mtp_MtpDatabase(JNIEnv *env);
extern int register_android_mtp_MtpDevice(JNIEnv *env);
extern int register_android_mtp_MtpServer(JNIEnv *env);
+extern int register_android_media_MediaTranscodeManager(JNIEnv *env);
jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
@@ -1565,6 +1566,11 @@
goto bail;
}
+ if (register_android_media_MediaTranscodeManager(env) < 0) {
+ ALOGE("ERROR: MediaTranscodeManager native registration failed");
+ goto bail;
+ }
+
/* success -- return valid version number */
result = JNI_VERSION_1_4;
diff --git a/media/jni/android_media_MediaTranscodeManager.cpp b/media/jni/android_media_MediaTranscodeManager.cpp
new file mode 100644
index 0000000..0b4048c
--- /dev/null
+++ b/media/jni/android_media_MediaTranscodeManager.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2019, 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.
+ */
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaTranscodeManager_JNI"
+
+#include "android_runtime/AndroidRuntime.h"
+#include "jni.h"
+
+#include <nativehelper/JNIHelp.h>
+#include <utils/Log.h>
+
+namespace {
+
+// NOTE: Keep these enums in sync with their equivalents in MediaTranscodeManager.java.
+enum {
+ ID_INVALID = -1
+};
+
+enum {
+ EVENT_JOB_STARTED = 1,
+ EVENT_JOB_PROGRESSED = 2,
+ EVENT_JOB_FINISHED = 3,
+};
+
+enum {
+ RESULT_NONE = 1,
+ RESULT_SUCCESS = 2,
+ RESULT_ERROR = 3,
+ RESULT_CANCELED = 4,
+};
+
+struct {
+ jmethodID postEventFromNative;
+} gMediaTranscodeManagerClassInfo;
+
+using namespace android;
+
+void android_media_MediaTranscodeManager_native_init(JNIEnv *env, jclass clazz) {
+ ALOGV("android_media_MediaTranscodeManager_native_init");
+
+ gMediaTranscodeManagerClassInfo.postEventFromNative = env->GetMethodID(
+ clazz, "postEventFromNative", "(IJI)V");
+ LOG_ALWAYS_FATAL_IF(gMediaTranscodeManagerClassInfo.postEventFromNative == NULL,
+ "can't find android/media/MediaTranscodeManager.postEventFromNative");
+}
+
+jlong android_media_MediaTranscodeManager_requestUniqueJobID(
+ JNIEnv *env __unused, jobject thiz __unused) {
+ ALOGV("android_media_MediaTranscodeManager_reserveUniqueJobID");
+ static std::atomic_int32_t sJobIDCounter{0};
+ jlong id = (jlong)++sJobIDCounter;
+ return id;
+}
+
+jboolean android_media_MediaTranscodeManager_enqueueTranscodingRequest(
+ JNIEnv *env, jobject thiz, jlong id, jobject request, jobject context __unused) {
+ ALOGV("android_media_MediaTranscodeManager_enqueueTranscodingRequest");
+ if (!request) {
+ return ID_INVALID;
+ }
+
+ env->CallVoidMethod(thiz, gMediaTranscodeManagerClassInfo.postEventFromNative,
+ EVENT_JOB_FINISHED, id, RESULT_ERROR);
+ return true;
+}
+
+void android_media_MediaTranscodeManager_cancelTranscodingRequest(
+ JNIEnv *env __unused, jobject thiz __unused, jlong jobID __unused) {
+ ALOGV("android_media_MediaTranscodeManager_cancelTranscodingRequest");
+}
+
+const JNINativeMethod gMethods[] = {
+ { "native_init", "()V",
+ (void *)android_media_MediaTranscodeManager_native_init },
+ { "native_requestUniqueJobID", "()J",
+ (void *)android_media_MediaTranscodeManager_requestUniqueJobID },
+ { "native_enqueueTranscodingRequest",
+ "(JLandroid/media/MediaTranscodeManager$TranscodingRequest;Landroid/content/Context;)Z",
+ (void *)android_media_MediaTranscodeManager_enqueueTranscodingRequest },
+ { "native_cancelTranscodingRequest", "(J)V",
+ (void *)android_media_MediaTranscodeManager_cancelTranscodingRequest },
+};
+
+} // namespace anonymous
+
+int register_android_media_MediaTranscodeManager(JNIEnv *env) {
+ return AndroidRuntime::registerNativeMethods(env,
+ "android/media/MediaTranscodeManager", gMethods, NELEM(gMethods));
+}
diff --git a/media/tests/MediaFrameworkTest/Android.bp b/media/tests/MediaFrameworkTest/Android.bp
index f0fbc50..ecbe2b3 100644
--- a/media/tests/MediaFrameworkTest/Android.bp
+++ b/media/tests/MediaFrameworkTest/Android.bp
@@ -7,6 +7,7 @@
],
static_libs: [
"mockito-target-minus-junit4",
+ "androidx.test.ext.junit",
"androidx.test.rules",
"android-ex-camera2",
],
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediatranscodemanager/MediaTranscodeManagerTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediatranscodemanager/MediaTranscodeManagerTest.java
new file mode 100644
index 0000000..eeda50e
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediatranscodemanager/MediaTranscodeManagerTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 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.mediaframeworktest.functional.mediatranscodemanager;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.media.MediaTranscodeManager;
+import android.util.Log;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class MediaTranscodeManagerTest {
+ private static final String TAG = "MediaTranscodeManagerTest";
+
+ /** The time to wait for the transcode operation to complete before failing the test. */
+ private static final int TRANSCODE_TIMEOUT_SECONDS = 2;
+
+ @Test
+ public void testMediaTranscodeManager() throws InterruptedException {
+ Log.d(TAG, "Starting: testMediaTranscodeManager");
+
+ Semaphore transcodeCompleteSemaphore = new Semaphore(0);
+ MediaTranscodeManager.TranscodingRequest request =
+ new MediaTranscodeManager.TranscodingRequest.Builder().build();
+ Executor listenerExecutor = Executors.newSingleThreadExecutor();
+
+ MediaTranscodeManager mediaTranscodeManager =
+ MediaTranscodeManager.getInstance(ApplicationProvider.getApplicationContext());
+ assertNotNull(mediaTranscodeManager);
+
+ MediaTranscodeManager.TranscodingJob job;
+ job = mediaTranscodeManager.enqueueTranscodingRequest(request, listenerExecutor,
+ transcodingJob -> {
+ Log.d(TAG, "Transcoding completed with result: " + transcodingJob.getResult());
+ transcodeCompleteSemaphore.release();
+ });
+ assertNotNull(job);
+
+ job.setOnProgressChangedListener(
+ listenerExecutor, progress -> Log.d(TAG, "Progress: " + progress));
+
+ if (job != null) {
+ Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to complete.");
+ boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
+ TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ assertTrue("Transcode failed to complete in time.", finishedOnTime);
+ }
+ }
+}
diff --git a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
index 221783b..ed93112 100644
--- a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
@@ -172,7 +172,7 @@
MediaRoute2Info route = mRoutes.get(routeId);
if (route == null || TextUtils.equals(ROUTE_ID3_SESSION_CREATION_FAILED, routeId)) {
// Tell the router that session cannot be created by passing null as sessionInfo.
- notifySessionCreated(/* sessionInfo= */ null, requestId);
+ notifySessionCreationFailed(requestId);
return;
}
maybeDeselectRoute(routeId);
@@ -196,8 +196,13 @@
}
@Override
- public void onDestroySession(String sessionId, RoutingSessionInfo lastSessionInfo) {
- for (String routeId : lastSessionInfo.getSelectedRoutes()) {
+ public void onReleaseSession(String sessionId) {
+ RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
+ if (sessionInfo == null) {
+ return;
+ }
+
+ for (String routeId : sessionInfo.getSelectedRoutes()) {
mRouteIdToSessionId.remove(routeId);
MediaRoute2Info route = mRoutes.get(routeId);
if (route != null) {
@@ -206,6 +211,7 @@
.build());
}
}
+ notifySessionReleased(sessionId);
}
@Override
@@ -227,8 +233,7 @@
.removeSelectableRoute(routeId)
.addDeselectableRoute(routeId)
.build();
- updateSessionInfo(newSessionInfo);
- notifySessionInfoChanged(newSessionInfo);
+ notifySessionUpdated(newSessionInfo);
}
@Override
@@ -247,7 +252,7 @@
.build());
if (sessionInfo.getSelectedRoutes().size() == 1) {
- releaseSession(sessionId);
+ notifySessionReleased(sessionId);
return;
}
@@ -256,8 +261,7 @@
.addSelectableRoute(routeId)
.removeDeselectableRoute(routeId)
.build();
- updateSessionInfo(newSessionInfo);
- notifySessionInfoChanged(newSessionInfo);
+ notifySessionUpdated(newSessionInfo);
}
@Override
@@ -269,8 +273,7 @@
.removeDeselectableRoute(routeId)
.removeTransferrableRoute(routeId)
.build();
- updateSessionInfo(newSessionInfo);
- notifySessionInfoChanged(newSessionInfo);
+ notifySessionUpdated(newSessionInfo);
}
void maybeDeselectRoute(String routeId) {
diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp
index 1aebeaf..26c7f8d 100644
--- a/native/graphics/jni/bitmap.cpp
+++ b/native/graphics/jni/bitmap.cpp
@@ -16,6 +16,7 @@
#include <android/bitmap.h>
#include <android/graphics/bitmap.h>
+#include <android/data_space.h>
int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
AndroidBitmapInfo* info) {
@@ -29,6 +30,15 @@
return ANDROID_BITMAP_RESULT_SUCCESS;
}
+int32_t AndroidBitmap_getDataSpace(JNIEnv* env, jobject jbitmap) {
+ if (NULL == env || NULL == jbitmap) {
+ return ADATASPACE_UNKNOWN; // Or return a real error?
+ }
+
+ android::graphics::Bitmap bitmap(env, jbitmap);
+ return bitmap.getDataSpace();
+}
+
int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr) {
if (NULL == env || NULL == jbitmap) {
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
diff --git a/native/graphics/jni/libjnigraphics.map.txt b/native/graphics/jni/libjnigraphics.map.txt
index bdd7f63..832770f 100644
--- a/native/graphics/jni/libjnigraphics.map.txt
+++ b/native/graphics/jni/libjnigraphics.map.txt
@@ -18,6 +18,7 @@
AImageDecoderHeaderInfo_isAnimated;
AImageDecoderHeaderInfo_getAndroidBitmapFormat;
AndroidBitmap_getInfo;
+ AndroidBitmap_getDataSpace;
AndroidBitmap_lockPixels;
AndroidBitmap_unlockPixels;
local:
diff --git a/packages/CarSystemUI/res/layout/sysui_primary_window.xml b/packages/CarSystemUI/res/layout/sysui_primary_window.xml
index 309d9ef..cc36e87 100644
--- a/packages/CarSystemUI/res/layout/sysui_primary_window.xml
+++ b/packages/CarSystemUI/res/layout/sysui_primary_window.xml
@@ -15,9 +15,16 @@
~ limitations under the License.
-->
+<!-- Fullscreen views in sysui should be listed here in increasing Z order. -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent">
+
+ <ViewStub android:id="@+id/fullscreen_user_switcher_stub"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout="@layout/car_fullscreen_user_switcher"/>
+
</FrameLayout>
\ No newline at end of file
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
index 6ec3854..cfe1c70 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
@@ -22,7 +22,7 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.util.leak.LeakDetector;
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/SystemUIPrimaryWindowController.java b/packages/CarSystemUI/src/com/android/systemui/car/SystemUIPrimaryWindowController.java
index e3e9ab7..c7e14d6 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/SystemUIPrimaryWindowController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/SystemUIPrimaryWindowController.java
@@ -54,6 +54,7 @@
private ViewGroup mBaseLayout;
private WindowManager.LayoutParams mLp;
private WindowManager.LayoutParams mLpChanged;
+ private boolean mIsAttached = false;
@Inject
public SystemUIPrimaryWindowController(
@@ -86,8 +87,17 @@
return mBaseLayout;
}
+ /** Returns {@code true} if the window is already attached. */
+ public boolean isAttached() {
+ return mIsAttached;
+ }
+
/** Attaches the window to the window manager. */
public void attach() {
+ if (mIsAttached) {
+ return;
+ }
+ mIsAttached = true;
// Now that the status bar window encompasses the sliding panel and its
// translucent backdrop, the entire thing is made TRANSLUCENT and is
// hardware-accelerated.
@@ -98,13 +108,14 @@
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT);
mLp.token = new Binder();
mLp.gravity = Gravity.TOP;
mLp.setFitWindowInsetsTypes(/* types= */ 0);
mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
- mLp.setTitle("NotificationShade");
+ mLp.setTitle("SystemUIPrimaryWindow");
mLp.packageName = mContext.getPackageName();
mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -118,8 +129,11 @@
// TODO: Update this so that the windowing type gets the full height of the display
// when we use MATCH_PARENT.
mLpChanged.height = mDisplayHeight + mNavBarHeight;
+ mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
} else {
mLpChanged.height = mStatusBarHeight;
+ // TODO: Allow touches to go through to the status bar to handle notification panel.
+ mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
}
updateWindow();
}
@@ -131,7 +145,9 @@
private void updateWindow() {
if (mLp != null && mLp.copyFrom(mLpChanged) != 0) {
- mWindowManager.updateViewLayout(mBaseLayout, mLp);
+ if (isAttached()) {
+ mWindowManager.updateViewLayout(mBaseLayout, mLp);
+ }
}
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 4521f5f..18485dc 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -67,6 +67,7 @@
import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.CarDeviceProvisionedListener;
import com.android.systemui.car.CarServiceProvider;
+import com.android.systemui.car.SystemUIPrimaryWindowController;
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.UiBackground;
@@ -106,8 +107,8 @@
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -168,6 +169,7 @@
// acceleration rate for the fling animation
private static final float FLING_SPEED_UP_FACTOR = 0.6f;
+ private final UserSwitcherController mUserSwitcherController;
private final ScrimController mScrimController;
private final LockscreenLockIconController mLockscreenLockIconController;
@@ -177,17 +179,16 @@
private float mBackgroundAlphaDiff;
private float mInitialBackgroundAlpha;
- private final Lazy<FullscreenUserSwitcher> mFullscreenUserSwitcherLazy;
- private FullscreenUserSwitcher mFullscreenUserSwitcher;
-
private CarBatteryController mCarBatteryController;
private BatteryMeterView mBatteryMeterView;
private Drawable mNotificationPanelBackground;
private final Object mQueueLock = new Object();
+ private final SystemUIPrimaryWindowController mSystemUIPrimaryWindowController;
private final CarNavigationBarController mCarNavigationBarController;
private final FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
private final Lazy<PowerManagerHelper> mPowerManagerHelperLazy;
+ private final FullscreenUserSwitcher mFullscreenUserSwitcher;
private final ShadeController mShadeController;
private final CarServiceProvider mCarServiceProvider;
private final CarDeviceProvisionedController mCarDeviceProvisionedController;
@@ -268,7 +269,7 @@
HeadsUpManagerPhone headsUpManagerPhone,
DynamicPrivacyController dynamicPrivacyController,
BypassHeadsUpNotifier bypassHeadsUpNotifier,
- Lazy<NewNotifPipeline> newNotifPipeline,
+ Lazy<NotifPipelineInitializer> notifPipelineInitializer,
FalsingManager falsingManager,
BroadcastDispatcher broadcastDispatcher,
RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
@@ -338,7 +339,8 @@
/* Car Settings injected components. */
CarServiceProvider carServiceProvider,
Lazy<PowerManagerHelper> powerManagerHelperLazy,
- Lazy<FullscreenUserSwitcher> fullscreenUserSwitcherLazy,
+ FullscreenUserSwitcher fullscreenUserSwitcher,
+ SystemUIPrimaryWindowController systemUIPrimaryWindowController,
CarNavigationBarController carNavigationBarController,
FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
super(
@@ -355,7 +357,7 @@
headsUpManagerPhone,
dynamicPrivacyController,
bypassHeadsUpNotifier,
- newNotifPipeline,
+ notifPipelineInitializer,
falsingManager,
broadcastDispatcher,
remoteInputQuickSettingsDisabler,
@@ -422,6 +424,7 @@
userInfoControllerImpl,
notificationRowBinder,
dismissCallbackRegistry);
+ mUserSwitcherController = userSwitcherController;
mScrimController = scrimController;
mLockscreenLockIconController = lockscreenLockIconController;
mCarDeviceProvisionedController =
@@ -429,7 +432,8 @@
mShadeController = shadeController;
mCarServiceProvider = carServiceProvider;
mPowerManagerHelperLazy = powerManagerHelperLazy;
- mFullscreenUserSwitcherLazy = fullscreenUserSwitcherLazy;
+ mFullscreenUserSwitcher = fullscreenUserSwitcher;
+ mSystemUIPrimaryWindowController = systemUIPrimaryWindowController;
mCarNavigationBarController = carNavigationBarController;
mFlingAnimationUtilsBuilder = flingAnimationUtilsBuilder;
}
@@ -444,6 +448,13 @@
mScreenLifecycle = Dependency.get(ScreenLifecycle.class);
mScreenLifecycle.addObserver(mScreenObserver);
+ // TODO: Remove the setup of user switcher from Car Status Bar.
+ mSystemUIPrimaryWindowController.attach();
+ mFullscreenUserSwitcher.setStatusBar(this);
+ mFullscreenUserSwitcher.setContainer(
+ mSystemUIPrimaryWindowController.getBaseLayout().findViewById(
+ R.id.fullscreen_user_switcher_stub));
+
// Notification bar related setup.
mInitialBackgroundAlpha = (float) mContext.getResources().getInteger(
R.integer.config_initialNotificationBackgroundAlpha) / 100;
@@ -510,16 +521,6 @@
});
}
- /**
- * Allows for showing or hiding just the navigation bars. This is indented to be used when
- * the full screen user selector is shown.
- */
- void setNavBarVisibility(@View.Visibility int visibility) {
- mCarNavigationBarController.setBottomWindowVisibility(visibility);
- mCarNavigationBarController.setLeftWindowVisibility(visibility);
- mCarNavigationBarController.setRightWindowVisibility(visibility);
- }
-
@Override
public boolean hideKeyguard() {
boolean result = super.hideKeyguard();
@@ -924,9 +925,6 @@
+ " scroll " + mStackScroller.getScrollX()
+ "," + mStackScroller.getScrollY());
}
-
- pw.print(" mFullscreenUserSwitcher=");
- pw.println(mFullscreenUserSwitcher);
pw.print(" mCarBatteryController=");
pw.println(mCarBatteryController);
pw.print(" mBatteryMeterView=");
@@ -972,14 +970,7 @@
@Override
protected void createUserSwitcher() {
- UserSwitcherController userSwitcherController =
- Dependency.get(UserSwitcherController.class);
- if (userSwitcherController.useFullscreenUserSwitcher()) {
- mFullscreenUserSwitcher = mFullscreenUserSwitcherLazy.get();
- mFullscreenUserSwitcher.setStatusBar(this);
- mFullscreenUserSwitcher.setContainer(
- mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub));
- } else {
+ if (!mUserSwitcherController.useFullscreenUserSwitcher()) {
super.createUserSwitcher();
}
}
@@ -996,25 +987,12 @@
super.onStateChanged(newState);
if (newState != StatusBarState.FULLSCREEN_USER_SWITCHER) {
- hideUserSwitcher();
+ mFullscreenUserSwitcher.hide();
} else {
dismissKeyguardWhenUserSwitcherNotDisplayed();
}
}
- /** Makes the full screen user switcher visible, if applicable. */
- public void showUserSwitcher() {
- if (mFullscreenUserSwitcher != null && mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
- mFullscreenUserSwitcher.show(); // Makes the switcher visible.
- }
- }
-
- private void hideUserSwitcher() {
- if (mFullscreenUserSwitcher != null) {
- mFullscreenUserSwitcher.hide();
- }
- }
-
final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
@Override
public void onScreenTurnedOn() {
@@ -1024,7 +1002,7 @@
// We automatically dismiss keyguard unless user switcher is being shown on the keyguard.
private void dismissKeyguardWhenUserSwitcherNotDisplayed() {
- if (mFullscreenUserSwitcher == null) {
+ if (!mUserSwitcherController.useFullscreenUserSwitcher()) {
return; // Not using the full screen user switcher.
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
index 0ad0992..2a2eb69 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarKeyguardViewManager.java
@@ -24,6 +24,7 @@
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.R;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.navigationbar.car.CarNavigationBarController;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.phone.NavigationModeController;
@@ -40,6 +41,8 @@
public class CarStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager {
protected boolean mShouldHideNavBar;
+ private final CarNavigationBarController mCarNavigationBarController;
+ private final FullscreenUserSwitcher mFullscreenUserSwitcher;
@Inject
public CarStatusBarKeyguardViewManager(Context context,
@@ -52,13 +55,17 @@
DockManager dockManager,
StatusBarWindowController statusBarWindowController,
KeyguardStateController keyguardStateController,
- NotificationMediaManager notificationMediaManager) {
+ NotificationMediaManager notificationMediaManager,
+ CarNavigationBarController carNavigationBarController,
+ FullscreenUserSwitcher fullscreenUserSwitcher) {
super(context, callback, lockPatternUtils, sysuiStatusBarStateController,
configurationController, keyguardUpdateMonitor, navigationModeController,
dockManager, statusBarWindowController, keyguardStateController,
notificationMediaManager);
mShouldHideNavBar = context.getResources()
.getBoolean(R.bool.config_hideNavWhenKeyguardBouncerShown);
+ mCarNavigationBarController = carNavigationBarController;
+ mFullscreenUserSwitcher = fullscreenUserSwitcher;
}
@Override
@@ -66,8 +73,10 @@
if (!mShouldHideNavBar) {
return;
}
- CarStatusBar statusBar = (CarStatusBar) mStatusBar;
- statusBar.setNavBarVisibility(navBarVisible ? View.VISIBLE : View.GONE);
+ int visibility = navBarVisible ? View.VISIBLE : View.GONE;
+ mCarNavigationBarController.setBottomWindowVisibility(visibility);
+ mCarNavigationBarController.setLeftWindowVisibility(visibility);
+ mCarNavigationBarController.setRightWindowVisibility(visibility);
}
/**
@@ -86,8 +95,7 @@
*/
@Override
public void onCancelClicked() {
- CarStatusBar statusBar = (CarStatusBar) mStatusBar;
- statusBar.showUserSwitcher();
+ mFullscreenUserSwitcher.show();
}
/**
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
index e5a091f..3abbe32 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
@@ -31,6 +31,7 @@
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.car.CarServiceProvider;
+import com.android.systemui.car.SystemUIPrimaryWindowController;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.keyguard.DismissCallbackRegistry;
@@ -66,8 +67,8 @@
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -138,7 +139,7 @@
HeadsUpManagerPhone headsUpManagerPhone,
DynamicPrivacyController dynamicPrivacyController,
BypassHeadsUpNotifier bypassHeadsUpNotifier,
- Lazy<NewNotifPipeline> newNotifPipeline,
+ Lazy<NotifPipelineInitializer> notifPipelineInitializer,
FalsingManager falsingManager,
BroadcastDispatcher broadcastDispatcher,
RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
@@ -207,7 +208,8 @@
DismissCallbackRegistry dismissCallbackRegistry,
CarServiceProvider carServiceProvider,
Lazy<PowerManagerHelper> powerManagerHelperLazy,
- Lazy<FullscreenUserSwitcher> fullscreenUserSwitcherLazy,
+ FullscreenUserSwitcher fullscreenUserSwitcher,
+ SystemUIPrimaryWindowController systemUIPrimaryWindowController,
CarNavigationBarController carNavigationBarController,
FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
return new CarStatusBar(
@@ -224,7 +226,7 @@
headsUpManagerPhone,
dynamicPrivacyController,
bypassHeadsUpNotifier,
- newNotifPipeline,
+ notifPipelineInitializer,
falsingManager,
broadcastDispatcher,
remoteInputQuickSettingsDisabler,
@@ -292,7 +294,8 @@
dismissCallbackRegistry,
carServiceProvider,
powerManagerHelperLazy,
- fullscreenUserSwitcherLazy,
+ fullscreenUserSwitcher,
+ systemUIPrimaryWindowController,
carNavigationBarController,
flingAnimationUtilsBuilder);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index f8fc3bb..3cd66c2 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -38,6 +38,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.R;
import com.android.systemui.car.CarServiceProvider;
+import com.android.systemui.car.SystemUIPrimaryWindowController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.car.CarTrustAgentUnlockDialogHelper.OnHideListener;
import com.android.systemui.statusbar.car.UserGridRecyclerView.UserRecord;
@@ -56,9 +57,10 @@
private final UserManager mUserManager;
private final CarServiceProvider mCarServiceProvider;
private final CarTrustAgentUnlockDialogHelper mUnlockDialogHelper;
+ private final SystemUIPrimaryWindowController mSystemUIPrimaryWindowController;
+ private CarStatusBar mCarStatusBar;
private final int mShortAnimDuration;
- private CarStatusBar mStatusBar;
private View mParent;
private UserGridRecyclerView mUserGridView;
private CarTrustAgentEnrollmentManager mEnrollmentManager;
@@ -81,23 +83,35 @@
@Main Resources resources,
UserManager userManager,
CarServiceProvider carServiceProvider,
- CarTrustAgentUnlockDialogHelper carTrustAgentUnlockDialogHelper) {
+ CarTrustAgentUnlockDialogHelper carTrustAgentUnlockDialogHelper,
+ SystemUIPrimaryWindowController systemUIPrimaryWindowController) {
mContext = context;
mResources = resources;
mUserManager = userManager;
mCarServiceProvider = carServiceProvider;
mUnlockDialogHelper = carTrustAgentUnlockDialogHelper;
+ mSystemUIPrimaryWindowController = systemUIPrimaryWindowController;
mShortAnimDuration = mResources.getInteger(android.R.integer.config_shortAnimTime);
}
- /** Sets the status bar which controls the keyguard. */
+ /** Sets the status bar which gives an entry point to dismiss the keyguard. */
+ // TODO: Remove this in favor of a keyguard controller.
public void setStatusBar(CarStatusBar statusBar) {
- mStatusBar = statusBar;
+ mCarStatusBar = statusBar;
+ }
+
+ /** Returns {@code true} if the user switcher already has a parent view. */
+ public boolean isAttached() {
+ return mParent != null;
}
/** Sets the {@link ViewStub} to show the user switcher. */
public void setContainer(ViewStub containerStub) {
+ if (isAttached()) {
+ return;
+ }
+
mParent = containerStub.inflate();
View container = mParent.findViewById(R.id.container);
@@ -148,20 +162,31 @@
* Makes user grid visible.
*/
public void show() {
+ if (!isAttached()) {
+ return;
+ }
mParent.setVisibility(View.VISIBLE);
+ mSystemUIPrimaryWindowController.setWindowExpanded(true);
}
/**
* Hides the user grid.
*/
public void hide() {
+ if (!isAttached()) {
+ return;
+ }
mParent.setVisibility(View.INVISIBLE);
+ mSystemUIPrimaryWindowController.setWindowExpanded(false);
}
/**
* @return {@code true} if user grid is visible, {@code false} otherwise.
*/
public boolean isVisible() {
+ if (!isAttached()) {
+ return false;
+ }
return mParent.getVisibility() == View.VISIBLE;
}
@@ -196,7 +221,7 @@
}
if (mSelectedUser.mType == UserRecord.FOREGROUND_USER) {
hide();
- mStatusBar.dismissKeyguard();
+ mCarStatusBar.dismissKeyguard();
return;
}
// Switching is about to happen, since it takes time, fade out the switcher gradually.
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index cdabeeb..8c756ec 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -43,6 +43,9 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowInsets;
+import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
@@ -53,7 +56,6 @@
import com.android.internal.util.UserIcons;
import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -337,7 +339,7 @@
.setPositiveButton(android.R.string.ok, null)
.create();
// Sets window flags for the SysUI dialog
- SystemUIDialog.applyFlags(maxUsersDialog);
+ applyCarSysUIDialogFlags(maxUsersDialog);
maxUsersDialog.show();
}
@@ -356,10 +358,19 @@
.setOnCancelListener(this)
.create();
// Sets window flags for the SysUI dialog
- SystemUIDialog.applyFlags(addUserDialog);
+ applyCarSysUIDialogFlags(addUserDialog);
addUserDialog.show();
}
+ private void applyCarSysUIDialogFlags(AlertDialog dialog) {
+ final Window window = dialog.getWindow();
+ window.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL);
+ window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+ | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
+ window.setFitWindowInsetsTypes(
+ window.getFitWindowInsetsTypes() & ~WindowInsets.Type.statusBars());
+ }
+
private void notifyUserSelected(UserRecord userRecord) {
// Notify the listener which user was selected
if (mUserSelectionListener != null) {
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index 2697a10..cb062a6 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -30,8 +30,6 @@
import android.text.TextUtils;
import android.util.Log;
-import com.android.internal.telephony.PhoneConstants;
-
/**
* This util class provides common logic for carrier actions
*/
@@ -103,7 +101,7 @@
}
private static void onDisableAllMeteredApns(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onDisableAllMeteredApns subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
@@ -111,7 +109,7 @@
}
private static void onEnableAllMeteredApns(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onEnableAllMeteredApns subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
@@ -135,7 +133,7 @@
}
private static void onRegisterDefaultNetworkAvail(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onRegisterDefaultNetworkAvail subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
@@ -143,7 +141,7 @@
}
private static void onDeregisterDefaultNetworkAvail(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onDeregisterDefaultNetworkAvail subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
@@ -151,7 +149,7 @@
}
private static void onDisableRadio(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onDisableRadio subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
@@ -159,7 +157,7 @@
}
private static void onEnableRadio(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onEnableRadio subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
@@ -202,7 +200,7 @@
}
private static void onResetAllCarrierActions(Intent intent, Context context) {
- int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.getDefaultVoiceSubscriptionId());
logd("onResetAllCarrierActions subId: " + subId);
final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
index 086a287..6229434 100644
--- a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
+++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/CarrierDefaultReceiverTest.java
@@ -15,6 +15,7 @@
*/
package com.android.carrierdefaultapp;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
@@ -26,11 +27,10 @@
import android.content.Intent;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.test.InstrumentationTestCase;
-import com.android.internal.telephony.PhoneConstants;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -69,6 +69,7 @@
mContext.injectSystemService(NotificationManager.class, mNotificationMgr);
mContext.injectSystemService(TelephonyManager.class, mTelephonyMgr);
mContext.injectSystemService(CarrierConfigManager.class, mCarrierConfigMgr);
+ doReturn(mTelephonyMgr).when(mTelephonyMgr).createForSubscriptionId(anyInt());
mReceiver = new CarrierDefaultBroadcastReceiver();
}
@@ -88,7 +89,7 @@
doReturn(b).when(mCarrierConfigMgr).getConfig();
Intent intent = new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_REDIRECTED);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
mReceiver.onReceive(mContext, intent);
mContext.waitForMs(100);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 81739e0..9d4c24e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -211,13 +211,6 @@
private static final int EAP_WPA = 1; // WPA-EAP
private static final int EAP_WPA2_WPA3 = 2; // RSN-EAP
- /**
- * The number of distinct wifi levels.
- *
- * <p>Must keep in sync with {@link R.array.wifi_signal} and {@link WifiManager#RSSI_LEVELS}.
- */
- public static final int SIGNAL_LEVELS = 5;
-
public static final int UNREACHABLE_RSSI = Integer.MIN_VALUE;
public static final String KEY_PREFIX_AP = "AP:";
@@ -453,9 +446,10 @@
return other.getSpeed() - getSpeed();
}
+ WifiManager wifiManager = getWifiManager();
// Sort by signal strength, bucketed by level
- int difference = WifiManager.calculateSignalLevel(other.mRssi, SIGNAL_LEVELS)
- - WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
+ int difference = wifiManager.calculateSignalLevel(other.mRssi)
+ - wifiManager.calculateSignalLevel(mRssi);
if (difference != 0) {
return difference;
}
@@ -869,13 +863,14 @@
}
/**
- * Returns the number of levels to show for a Wifi icon, from 0 to {@link #SIGNAL_LEVELS}-1.
+ * Returns the number of levels to show for a Wifi icon, from 0 to
+ * {@link WifiManager#getMaxSignalLevel()}.
*
- * <p>Use {@#isReachable()} to determine if an AccessPoint is in range, as this method will
+ * <p>Use {@link #isReachable()} to determine if an AccessPoint is in range, as this method will
* always return at least 0.
*/
public int getLevel() {
- return WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
+ return getWifiManager().calculateSignalLevel(mRssi);
}
public int getRssi() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java b/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
index 4a4f0e6..f21e466 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
@@ -22,6 +22,7 @@
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Parcelable;
@@ -126,13 +127,15 @@
@Keep
public TestAccessPointBuilder setLevel(int level) {
// Reversal of WifiManager.calculateSignalLevels
+ WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
+ int maxSignalLevel = wifiManager.getMaxSignalLevel();
if (level == 0) {
mRssi = MIN_RSSI;
- } else if (level >= AccessPoint.SIGNAL_LEVELS) {
+ } else if (level > maxSignalLevel) {
mRssi = MAX_RSSI;
} else {
float inputRange = MAX_RSSI - MIN_RSSI;
- float outputRange = AccessPoint.SIGNAL_LEVELS - 1;
+ float outputRange = maxSignalLevel;
mRssi = (int) (level * inputRange / outputRange + MIN_RSSI);
}
return this;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 8591116..3f55cea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -89,7 +89,7 @@
public void setListening(boolean listening) {
if (listening) {
mNetworkScoreManager.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
- mWifiNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);
+ mWifiNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_CURRENT_NETWORK);
mWifiNetworkScoreCache.registerListener(mCacheListener);
mConnectivityManager.registerNetworkCallback(
mNetworkRequest, mNetworkCallback, mHandler);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index ba6a8ea..ed4ff08 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -361,7 +361,7 @@
mNetworkScoreManager.registerNetworkScoreCache(
NetworkKey.TYPE_WIFI,
mScoreCache,
- NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS);
+ NetworkScoreManager.SCORE_FILTER_SCAN_RESULTS);
}
private void requestScoresForNetworkKeys(Collection<NetworkKey> keys) {
diff --git a/packages/SettingsLib/tests/integ/Android.bp b/packages/SettingsLib/tests/integ/Android.bp
index 4600793..2ccff1e 100644
--- a/packages/SettingsLib/tests/integ/Android.bp
+++ b/packages/SettingsLib/tests/integ/Android.bp
@@ -14,7 +14,10 @@
android_test {
name: "SettingsLibTests",
- defaults: ["SettingsLibDefaults"],
+ defaults: [
+ "SettingsLibDefaults",
+ "framework-wifi-test-defaults"
+ ],
certificate: "platform",
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 61cbbd3..03201ae 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -83,7 +83,6 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class AccessPointTest {
-
private static final String TEST_SSID = "\"test_ssid\"";
private static final String ROAMING_SSID = "\"roaming_ssid\"";
private static final String OSU_FRIENDLY_NAME = "osu_friendly_name";
@@ -98,6 +97,7 @@
20 * DateUtils.MINUTE_IN_MILLIS;
private Context mContext;
+ private int mMaxSignalLevel;
private WifiInfo mWifiInfo;
@Mock private Context mMockContext;
@Mock private WifiManager mMockWifiManager;
@@ -128,6 +128,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = InstrumentationRegistry.getTargetContext();
+ mMaxSignalLevel = mContext.getSystemService(WifiManager.class).getMaxSignalLevel();
mWifiInfo = new WifiInfo();
mWifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(TEST_SSID));
mWifiInfo.setBSSID(TEST_BSSID);
@@ -180,7 +181,7 @@
@Test
public void testCompareTo_GivesHighLevelBeforeLowLevel() {
- final int highLevel = AccessPoint.SIGNAL_LEVELS - 1;
+ final int highLevel = mMaxSignalLevel;
final int lowLevel = 1;
assertThat(highLevel).isGreaterThan(lowLevel);
@@ -226,7 +227,7 @@
.setReachable(true).build();
AccessPoint saved = new TestAccessPointBuilder(mContext).setSaved(true).build();
AccessPoint highLevelAndReachable = new TestAccessPointBuilder(mContext)
- .setLevel(AccessPoint.SIGNAL_LEVELS - 1).build();
+ .setLevel(mMaxSignalLevel).build();
AccessPoint firstName = new TestAccessPointBuilder(mContext).setSsid("a").build();
AccessPoint lastname = new TestAccessPointBuilder(mContext).setSsid("z").build();
@@ -520,6 +521,8 @@
when(packageManager.getApplicationInfoAsUser(eq(appPackageName), anyInt(), anyInt()))
.thenReturn(applicationInfo);
when(applicationInfo.loadLabel(packageManager)).thenReturn(appLabel);
+ when(context.getSystemService(Context.WIFI_SERVICE)).thenReturn(mMockWifiManager);
+ when(mMockWifiManager.calculateSignalLevel(rssi)).thenReturn(4);
NetworkInfo networkInfo =
new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
@@ -636,14 +639,14 @@
public void testBuilder_setLevel() {
AccessPoint testAp;
- for (int i = 0; i < AccessPoint.SIGNAL_LEVELS; i++) {
+ for (int i = 0; i <= mMaxSignalLevel; i++) {
testAp = new TestAccessPointBuilder(mContext).setLevel(i).build();
assertThat(testAp.getLevel()).isEqualTo(i);
}
// numbers larger than the max level should be set to max
- testAp = new TestAccessPointBuilder(mContext).setLevel(AccessPoint.SIGNAL_LEVELS).build();
- assertThat(testAp.getLevel()).isEqualTo(AccessPoint.SIGNAL_LEVELS - 1);
+ testAp = new TestAccessPointBuilder(mContext).setLevel(mMaxSignalLevel + 1).build();
+ assertThat(testAp.getLevel()).isEqualTo(mMaxSignalLevel);
// numbers less than 0 should give level 0
testAp = new TestAccessPointBuilder(mContext).setLevel(-100).build();
@@ -653,7 +656,7 @@
@Test
public void testBuilder_settingReachableAfterLevelDoesNotAffectLevel() {
int level = 1;
- assertThat(level).isLessThan(AccessPoint.SIGNAL_LEVELS - 1);
+ assertThat(level).isLessThan(mMaxSignalLevel);
AccessPoint testAp =
new TestAccessPointBuilder(mContext).setLevel(level).setReachable(true).build();
diff --git a/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml
new file mode 100644
index 0000000..50aa212
--- /dev/null
+++ b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<!-- RelativeLayouts have an issue enforcing minimum heights, so just
+ work around this for now with LinearLayouts. -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:paddingTop="@dimen/global_actions_grid_item_vertical_margin"
+ android:paddingBottom="@dimen/global_actions_grid_item_vertical_margin"
+ android:paddingLeft="@dimen/global_actions_grid_item_side_margin"
+ android:paddingRight="@dimen/global_actions_grid_item_side_margin"
+ android:layout_marginRight="3dp"
+ android:layout_marginLeft="3dp"
+ android:background="@drawable/rounded_bg_full">
+ <LinearLayout
+ android:layout_width="@dimen/global_actions_grid_item_width"
+ android:layout_height="@dimen/global_actions_grid_item_height"
+ android:gravity="top|center_horizontal"
+ android:orientation="vertical">
+ <ImageView
+ android:id="@*android:id/icon"
+ android:layout_width="@dimen/global_actions_grid_item_icon_width"
+ android:layout_height="@dimen/global_actions_grid_item_icon_height"
+ android:layout_marginTop="@dimen/global_actions_grid_item_icon_top_margin"
+ android:layout_marginBottom="@dimen/global_actions_grid_item_icon_bottom_margin"
+ android:layout_marginLeft="@dimen/global_actions_grid_item_icon_side_margin"
+ android:layout_marginRight="@dimen/global_actions_grid_item_icon_side_margin"
+ android:scaleType="centerInside"
+ android:tint="@color/global_actions_text" />
+
+ <TextView
+ android:id="@*android:id/message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="marquee"
+ android:marqueeRepeatLimit="marquee_forever"
+ android:singleLine="true"
+ android:gravity="center"
+ android:textSize="12dp"
+ android:textColor="@color/global_actions_text"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ <TextView
+ android:visibility="gone"
+ android:id="@*android:id/status"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textColor="@color/global_actions_text"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/global_actions_grid_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_v2.xml
new file mode 100644
index 0000000..4cfb47e
--- /dev/null
+++ b/packages/SystemUI/res/layout/global_actions_grid_v2.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/global_actions_grid_root"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:layout_marginBottom="@dimen/global_actions_grid_container_negative_shadow_offset">
+
+ <com.android.systemui.globalactions.GlobalActionsFlatLayout
+ android:id="@id/global_actions_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:theme="@style/qs_theme"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ android:gravity="top | center_horizontal"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:paddingBottom="@dimen/global_actions_grid_container_shadow_offset"
+ android:layout_marginTop="@dimen/global_actions_top_margin"
+ android:layout_marginBottom="@dimen/global_actions_grid_container_negative_shadow_offset">
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layoutDirection="ltr"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:layout_marginBottom="@dimen/global_actions_grid_container_bottom_margin">
+ <!-- For separated items-->
+ <LinearLayout
+ android:id="@+id/separated_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="@dimen/global_actions_grid_side_margin"
+ android:layout_marginRight="@dimen/global_actions_grid_side_margin"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:translationZ="@dimen/global_actions_translate"
+ />
+ <!-- Grid of action items -->
+ <com.android.systemui.globalactions.ListGridLayout
+ android:id="@android:id/list"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="right"
+ android:layout_marginRight="@dimen/global_actions_grid_side_margin"
+ android:translationZ="@dimen/global_actions_translate"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
+ >
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="locale"
+ />
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="locale"
+ />
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="locale"
+ />
+ </com.android.systemui.globalactions.ListGridLayout>
+ </LinearLayout>
+ </com.android.systemui.globalactions.GlobalActionsFlatLayout>
+
+ <LinearLayout
+ android:id="@+id/global_actions_panel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/global_actions_view">
+
+ <FrameLayout
+ android:translationY="@dimen/global_actions_plugin_offset"
+ android:id="@+id/global_actions_panel_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:translationY="@dimen/global_actions_plugin_offset"
+ android:id="@+id/global_actions_controls"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/global_actions_panel">
+ <TextView
+ android:text="Home"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:gravity="center"
+ android:textSize="25dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:fontFamily="@*android:string/config_headlineFontFamily" />
+ <LinearLayout
+ android:id="@+id/global_actions_controls_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" />
+ </LinearLayout>
+ </androidx.constraintlayout.widget.ConstraintLayout>
+</ScrollView>
diff --git a/packages/SystemUI/res/layout/global_screenshot_action_chip.xml b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml
index 6b42400..366abaa 100644
--- a/packages/SystemUI/res/layout/global_screenshot_action_chip.xml
+++ b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml
@@ -14,12 +14,27 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/global_screenshot_action_chip"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginHorizontal="@dimen/screenshot_action_chip_margin_horizontal"
- android:paddingVertical="@dimen/screenshot_action_chip_padding_vertical"
- android:paddingHorizontal="@dimen/screenshot_action_chip_padding_horizontal"
- android:background="@drawable/action_chip_background"
- android:textColor="@color/global_screenshot_button_text"/>
+<com.android.systemui.screenshot.ScreenshotActionChip
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/global_screenshot_action_chip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginHorizontal="@dimen/screenshot_action_chip_margin_horizontal"
+ android:layout_gravity="center"
+ android:paddingVertical="@dimen/screenshot_action_chip_padding_vertical"
+ android:background="@drawable/action_chip_background"
+ android:gravity="center">
+ <ImageView
+ android:id="@+id/screenshot_action_chip_icon"
+ android:layout_width="@dimen/screenshot_action_chip_icon_size"
+ android:layout_height="@dimen/screenshot_action_chip_icon_size"
+ android:layout_marginStart="@dimen/screenshot_action_chip_padding_start"
+ android:layout_marginEnd="@dimen/screenshot_action_chip_padding_middle"/>
+ <TextView
+ android:id="@+id/screenshot_action_chip_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/screenshot_action_chip_padding_end"
+ android:textSize="@dimen/screenshot_action_chip_text_size"
+ android:textColor="@color/global_screenshot_button_text"/>
+</com.android.systemui.screenshot.ScreenshotActionChip>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 5a1151e..c26cb9a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -291,12 +291,17 @@
<dimen name="global_screenshot_legacy_bg_padding">20dp</dimen>
<dimen name="global_screenshot_bg_padding">20dp</dimen>
<dimen name="screenshot_action_container_corner_radius">10dp</dimen>
- <dimen name="screenshot_action_container_padding">20dp</dimen>
+ <dimen name="screenshot_action_container_padding">10dp</dimen>
<!-- Radius of the chip background on global screenshot actions -->
<dimen name="screenshot_button_corner_radius">20dp</dimen>
- <dimen name="screenshot_action_chip_margin_horizontal">10dp</dimen>
+ <dimen name="screenshot_action_chip_margin_horizontal">4dp</dimen>
<dimen name="screenshot_action_chip_padding_vertical">10dp</dimen>
- <dimen name="screenshot_action_chip_padding_horizontal">15dp</dimen>
+ <dimen name="screenshot_action_chip_icon_size">20dp</dimen>
+ <dimen name="screenshot_action_chip_padding_start">4dp</dimen>
+ <!-- Padding between icon and text -->
+ <dimen name="screenshot_action_chip_padding_middle">8dp</dimen>
+ <dimen name="screenshot_action_chip_padding_end">12dp</dimen>
+ <dimen name="screenshot_action_chip_text_size">14sp</dimen>
<!-- The width of the view containing navigation buttons -->
@@ -951,6 +956,9 @@
<dimen name="cell_overlay_padding">18dp</dimen>
<!-- Global actions power menu -->
+ <dimen name="global_actions_top_margin">12dp</dimen>
+ <dimen name="global_actions_plugin_offset">-145dp</dimen>
+
<dimen name="global_actions_panel_width">120dp</dimen>
<dimen name="global_actions_padding">12dp</dimen>
<dimen name="global_actions_translate">9dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index 8105faa..eab9706 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -27,9 +27,9 @@
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -49,7 +49,7 @@
public ForegroundServiceNotificationListener(Context context,
ForegroundServiceController foregroundServiceController,
NotificationEntryManager notificationEntryManager,
- NotifCollection notifCollection) {
+ NotifPipeline notifPipeline) {
mContext = context;
mForegroundServiceController = foregroundServiceController;
@@ -77,7 +77,7 @@
});
mEntryManager.addNotificationLifetimeExtender(new ForegroundServiceLifetimeExtender());
- notifCollection.addCollectionListener(new NotifCollectionListener() {
+ notifPipeline.addCollectionListener(new NotifCollectionListener() {
@Override
public void onEntryAdded(NotificationEntry entry) {
addNotification(entry, entry.getImportance());
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
index 563a0a7..31656a0 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
@@ -961,6 +961,13 @@
if (view != null) {
final SpringAnimation animation =
(SpringAnimation) view.getTag(getTagIdForProperty(property));
+
+ // If the animation is null, the view was probably removed from the layout before
+ // the animation started.
+ if (animation == null) {
+ return;
+ }
+
if (afterCallbacks != null) {
animation.addEndListener(new OneTimeEndListener() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index b195238..a6fa414 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -30,10 +30,8 @@
import com.android.systemui.recents.Recents;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.people.PeopleHubModule;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -113,9 +111,4 @@
@Singleton
@Binds
abstract SystemClock bindSystemClock(SystemClockImpl systemClock);
-
- @Singleton
- @Binds
- abstract NotifListBuilder bindNotifListBuilder(NotifListBuilderImpl impl);
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 91bb80c..c138462 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -59,7 +59,6 @@
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
-import android.text.TextUtils;
import android.util.ArraySet;
import android.util.FeatureFlagUtils;
import android.util.Log;
@@ -444,7 +443,8 @@
mKeyguardManager.isDeviceLocked())
: null;
- ActionsDialog dialog = new ActionsDialog(mContext, mAdapter, panelViewController);
+ ActionsDialog dialog = new ActionsDialog(
+ mContext, mAdapter, panelViewController, isControlsEnabled(mContext));
dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
dialog.setKeyguardShowing(mKeyguardShowing);
@@ -518,7 +518,7 @@
@Override
public boolean shouldBeSeparated() {
- return shouldUseSeparatedView();
+ return !isControlsEnabled(mContext);
}
@Override
@@ -1154,6 +1154,9 @@
}
protected int getActionLayoutId(Context context) {
+ if (isControlsEnabled(context)) {
+ return com.android.systemui.R.layout.global_actions_grid_item_v2;
+ }
return com.android.systemui.R.layout.global_actions_grid_item;
}
@@ -1415,8 +1418,8 @@
} else if (TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) {
// Airplane mode can be changed after ECM exits if airplane toggle button
// is pressed during ECM mode
- if (!(intent.getBooleanExtra("PHONE_IN_ECM_STATE", false)) &&
- mIsWaitingForEcmExit) {
+ if (!(intent.getBooleanExtra(TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, false))
+ && mIsWaitingForEcmExit) {
mIsWaitingForEcmExit = false;
changeAirplaneModeSystemSetting(true);
}
@@ -1526,15 +1529,18 @@
private ResetOrientationData mResetOrientationData;
private boolean mHadTopUi;
private final StatusBarWindowController mStatusBarWindowController;
+ private boolean mControlsEnabled;
ActionsDialog(Context context, MyAdapter adapter,
- GlobalActionsPanelPlugin.PanelViewController plugin) {
+ GlobalActionsPanelPlugin.PanelViewController plugin,
+ boolean controlsEnabled) {
super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
mContext = context;
mAdapter = adapter;
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
mStatusBarService = Dependency.get(IStatusBarService.class);
mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
+ mControlsEnabled = controlsEnabled;
// Window initialization
Window window = getWindow();
@@ -1651,6 +1657,10 @@
}
private int getGlobalActionsLayoutId(Context context) {
+ if (mControlsEnabled) {
+ return com.android.systemui.R.layout.global_actions_grid_v2;
+ }
+
int rotation = RotationUtils.getRotation(context);
boolean useGridLayout = isForceGridEnabled(context)
|| (shouldUsePanel() && rotation == RotationUtils.ROTATION_NONE);
@@ -1854,4 +1864,9 @@
private static boolean shouldUseSeparatedView() {
return true;
}
+
+ private static boolean isControlsEnabled(Context context) {
+ return Settings.Secure.getInt(
+ context.getContentResolver(), "systemui.controls_available", 0) == 1;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java
new file mode 100644
index 0000000..6749f1d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsFlatLayout.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2019 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.globalactions;
+
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Single row implementation of the button layout created by the global actions dialog.
+ */
+public class GlobalActionsFlatLayout extends GlobalActionsLayout {
+ public GlobalActionsFlatLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ mBackgroundsSet = true;
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ // backgrounds set only once, the first time onMeasure is called after inflation
+ // if (getListView() != null && !mBackgroundsSet) {
+ // setBackgrounds();
+ // mBackgroundsSet = true;
+ // }
+ }
+
+ @VisibleForTesting
+ protected void setupListView() {
+ ListGridLayout listView = getListView();
+ listView.setExpectedCount(Math.min(2, mAdapter.countListItems()));
+ listView.setReverseSublists(shouldReverseSublists());
+ listView.setReverseItems(shouldReverseListItems());
+ listView.setSwapRowsAndColumns(shouldSwapRowsAndColumns());
+ }
+
+ @Override
+ public void onUpdateList() {
+ setupListView();
+ super.onUpdateList();
+ updateSeparatedItemSize();
+ }
+
+ /**
+ * If the separated view contains only one item, expand the bounds of that item to take up the
+ * entire view, so that the whole thing is touch-able.
+ */
+ @VisibleForTesting
+ protected void updateSeparatedItemSize() {
+ ViewGroup separated = getSeparatedView();
+ if (separated.getChildCount() == 0) {
+ return;
+ }
+ View firstChild = separated.getChildAt(0);
+ ViewGroup.LayoutParams childParams = firstChild.getLayoutParams();
+
+ if (separated.getChildCount() == 1) {
+ childParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
+ childParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
+ } else {
+ childParams.width = ViewGroup.LayoutParams.WRAP_CONTENT;
+ childParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ }
+ }
+
+ @Override
+ protected ListGridLayout getListView() {
+ return (ListGridLayout) super.getListView();
+ }
+
+ @Override
+ protected void removeAllListViews() {
+ ListGridLayout list = getListView();
+ if (list != null) {
+ list.removeAllItems();
+ }
+ }
+
+ @Override
+ protected void addToListView(View v, boolean reverse) {
+ ListGridLayout list = getListView();
+ if (list != null) {
+ list.addItem(v);
+ }
+ }
+
+ @Override
+ public void removeAllItems() {
+ ViewGroup separatedList = getSeparatedView();
+ ListGridLayout list = getListView();
+ if (separatedList != null) {
+ separatedList.removeAllViews();
+ }
+ if (list != null) {
+ list.removeAllItems();
+ }
+ }
+
+ /**
+ * Determines whether the ListGridLayout should fill sublists in the reverse order.
+ * Used to account for sublist ordering changing between landscape and seascape views.
+ */
+ @VisibleForTesting
+ protected boolean shouldReverseSublists() {
+ if (getCurrentRotation() == ROTATION_SEASCAPE) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Determines whether the ListGridLayout should fill rows first instead of columns.
+ * Used to account for vertical/horizontal changes due to landscape or seascape rotations.
+ */
+ @VisibleForTesting
+ protected boolean shouldSwapRowsAndColumns() {
+ if (getCurrentRotation() == ROTATION_NONE) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ protected boolean shouldReverseListItems() {
+ int rotation = getCurrentRotation();
+ boolean reverse = false; // should we add items to parents in the reverse order?
+ if (rotation == ROTATION_NONE
+ || rotation == ROTATION_SEASCAPE) {
+ reverse = !reverse; // if we're in portrait or seascape, reverse items
+ }
+ if (getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+ reverse = !reverse; // if we're in an RTL language, reverse items (again)
+ }
+ return reverse;
+ }
+
+ @VisibleForTesting
+ protected float getAnimationDistance() {
+ int rows = getListView().getRowCount();
+ float gridItemSize = getContext().getResources().getDimension(
+ com.android.systemui.R.dimen.global_actions_grid_item_height);
+ return rows * gridItemSize / 2;
+ }
+
+ @Override
+ public float getAnimationOffsetX() {
+ switch (getCurrentRotation()) {
+ case ROTATION_LANDSCAPE:
+ return getAnimationDistance();
+ case ROTATION_SEASCAPE:
+ return -getAnimationDistance();
+ default: // Portrait
+ return 0;
+ }
+ }
+
+ @Override
+ public float getAnimationOffsetY() {
+ if (getCurrentRotation() == ROTATION_NONE) {
+ return getAnimationDistance();
+ }
+ return 0;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 9f2bbc6..27c9555 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -64,7 +64,6 @@
import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.TextView;
import android.widget.Toast;
import com.android.systemui.R;
@@ -529,9 +528,10 @@
mActionsView.removeAllViews();
for (Notification.Action action : actions) {
- TextView actionChip = (TextView) inflater.inflate(
+ ScreenshotActionChip actionChip = (ScreenshotActionChip) inflater.inflate(
R.layout.global_screenshot_action_chip, mActionsView, false);
actionChip.setText(action.title);
+ actionChip.setIcon(action.getIcon(), true);
actionChip.setOnClickListener(v -> {
try {
action.actionIntent.send();
@@ -545,11 +545,11 @@
}
if (DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI, SCREENSHOT_SCROLLING_ENABLED, false)) {
- TextView scrollChip = (TextView) inflater.inflate(
+ ScreenshotActionChip scrollChip = (ScreenshotActionChip) inflater.inflate(
R.layout.global_screenshot_action_chip, mActionsView, false);
Toast scrollNotImplemented = Toast.makeText(
mContext, "Not implemented", Toast.LENGTH_SHORT);
- scrollChip.setText("Scroll"); // TODO (mkephart): add resource and translate
+ scrollChip.setText("Extend"); // TODO (mkephart): add resource and translate
scrollChip.setOnClickListener(v -> scrollNotImplemented.show());
mActionsView.addView(scrollChip);
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java
new file mode 100644
index 0000000..6edacd1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java
@@ -0,0 +1,73 @@
+/*
+ * 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.screenshot;
+
+import android.annotation.ColorInt;
+import android.content.Context;
+import android.graphics.drawable.Icon;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+
+/**
+ * View for a chip with an icon and text.
+ */
+public class ScreenshotActionChip extends LinearLayout {
+
+ private ImageView mIcon;
+ private TextView mText;
+ private @ColorInt int mIconColor;
+
+ public ScreenshotActionChip(Context context) {
+ this(context, null);
+ }
+
+ public ScreenshotActionChip(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ScreenshotActionChip(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public ScreenshotActionChip(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ mIconColor = context.getColor(R.color.global_screenshot_button_text);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ mIcon = findViewById(R.id.screenshot_action_chip_icon);
+ mText = findViewById(R.id.screenshot_action_chip_text);
+ }
+
+ void setIcon(Icon icon, boolean tint) {
+ if (tint) {
+ icon.setTint(mIconColor);
+ }
+ mIcon.setImageIcon(icon);
+ }
+
+ void setText(CharSequence text) {
+ mText.setText(text);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 36dcaac..4a22831 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -43,7 +43,7 @@
import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.logging.NotifEvent;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
index e1268f6..73bfe25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
@@ -16,13 +16,11 @@
package com.android.systemui.statusbar.notification.collection;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
-
import java.util.List;
/**
- * Utility class for dumping the results of a {@link NotifListBuilder} to a debug string.
+ * Utility class for dumping the results of a {@link ShadeListBuilder} to a debug string.
*/
public class ListDumper {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 856b75b..4b15b7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -47,9 +47,13 @@
import android.util.Log;
import com.android.internal.statusbar.IStatusBarService;
-import com.android.systemui.statusbar.notification.collection.notifcollection.CoalescedEvent;
-import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer;
-import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer.BatchableNotificationHandler;
+import com.android.systemui.statusbar.notification.collection.coalescer.CoalescedEvent;
+import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
+import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer.BatchableNotificationHandler;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import com.android.systemui.util.Assert;
import java.lang.annotation.Retention;
@@ -123,36 +127,25 @@
* Sets the class responsible for converting the collection into the list of currently-visible
* notifications.
*/
- public void setBuildListener(CollectionReadyForBuildListener buildListener) {
+ void setBuildListener(CollectionReadyForBuildListener buildListener) {
Assert.isMainThread();
mBuildListener = buildListener;
}
- /**
- * Returns the list of "active" notifications, i.e. the notifications that are currently posted
- * to the phone. In general, this tracks closely to the list maintained by NotificationManager,
- * but it can diverge slightly due to lifetime extenders.
- *
- * The returned list is read-only, unsorted, unfiltered, and ungrouped.
- */
- public Collection<NotificationEntry> getNotifs() {
+ /** @see NotifPipeline#getActiveNotifs() */
+ Collection<NotificationEntry> getActiveNotifs() {
Assert.isMainThread();
return mReadOnlyNotificationSet;
}
- /**
- * Registers a listener to be informed when notifications are added, removed or updated.
- */
- public void addCollectionListener(NotifCollectionListener listener) {
+ /** @see NotifPipeline#addCollectionListener(NotifCollectionListener) */
+ void addCollectionListener(NotifCollectionListener listener) {
Assert.isMainThread();
mNotifCollectionListeners.add(listener);
}
- /**
- * Registers a lifetime extender. Lifetime extenders can cause notifications that have been
- * dismissed or retracted to be temporarily retained in the collection.
- */
- public void addNotificationLifetimeExtender(NotifLifetimeExtender extender) {
+ /** @see NotifPipeline#addNotificationLifetimeExtender(NotifLifetimeExtender) */
+ void addNotificationLifetimeExtender(NotifLifetimeExtender extender) {
Assert.isMainThread();
checkForReentrantCall();
if (mLifetimeExtenders.contains(extender)) {
@@ -165,7 +158,7 @@
/**
* Dismiss a notification on behalf of the user.
*/
- public void dismissNotification(
+ void dismissNotification(
NotificationEntry entry,
@CancellationReason int reason,
@NonNull DismissedByUserStats stats) {
@@ -446,7 +439,7 @@
REASON_TIMEOUT,
})
@Retention(RetentionPolicy.SOURCE)
- @interface CancellationReason {}
+ public @interface CancellationReason {}
public static final int REASON_UNKNOWN = 0;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
index 0d17557..e7b772f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
@@ -25,6 +25,9 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.notification.InflationException;
+import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
@@ -107,7 +110,7 @@
DISMISS_SENTIMENT_NEUTRAL,
NotificationVisibility.obtain(entry.getKey(),
entry.getRanking().getRank(),
- mNotifCollection.getNotifs().size(),
+ mNotifCollection.getActiveNotifs().size(),
true,
NotificationLogger.getNotificationLocation(entry))
));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java
new file mode 100644
index 0000000..7124517
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java
@@ -0,0 +1,191 @@
+/*
+ * 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.statusbar.notification.collection;
+
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.SectionsProvider;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
+
+import java.util.Collection;
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * The system that constructs the "shade list", the filtered, grouped, and sorted list of
+ * notifications that are currently being displayed to the user in the notification shade.
+ *
+ * The pipeline proceeds through a series of stages in order to produce the final list (see below).
+ * Each stage exposes hooks and listeners to allow other code to participate.
+ *
+ * This list differs from the canonical one we receive from system server in a few ways:
+ * - Filtered: Some notifications are filtered out. For example, we filter out notifications whose
+ * views haven't been inflated yet. We also filter out some notifications if we're on the lock
+ * screen and notifications for other users. So participate, see
+ * {@link #addPreGroupFilter} and similar methods.
+ * - Grouped: Notifications that are part of the same group are clustered together into a single
+ * GroupEntry. These groups are then transformed in order to remove children or completely split
+ * them apart. To participate, see {@link #addPromoter}.
+ * - Sorted: All top-level notifications are sorted. To participate, see
+ * {@link #setSectionsProvider} and {@link #setComparators}
+ *
+ * The exact order of all hooks is as follows:
+ * 0. Collection listeners are fired ({@link #addCollectionListener}).
+ * 1. Pre-group filters are fired on each notification ({@link #addPreGroupFilter}).
+ * 2. Initial grouping is performed (NotificationEntries will have their parents set
+ * appropriately).
+ * 3. OnBeforeTransformGroupListeners are fired ({@link #addOnBeforeTransformGroupsListener})
+ * 4. NotifPromoters are called on each notification with a parent ({@link #addPromoter})
+ * 5. OnBeforeSortListeners are fired ({@link #addOnBeforeSortListener})
+ * 6. SectionsProvider is called on each top-level entry in the list ({@link #setSectionsProvider})
+ * 7. Top-level entries within the same section are sorted by NotifComparators
+ * ({@link #setComparators})
+ * 8. Pre-render filters are fired on each notification ({@link #addPreRenderFilter})
+ * 9. OnBeforeRenderListListeners are fired ({@link #addOnBeforeRenderListListener})
+ * 9. The list is handed off to the view layer to be rendered
+ */
+@Singleton
+public class NotifPipeline {
+ private final NotifCollection mNotifCollection;
+ private final ShadeListBuilder mShadeListBuilder;
+
+ @Inject
+ public NotifPipeline(
+ NotifCollection notifCollection,
+ ShadeListBuilder shadeListBuilder) {
+ mNotifCollection = notifCollection;
+ mShadeListBuilder = shadeListBuilder;
+ }
+
+ /**
+ * Returns the list of "active" notifications, i.e. the notifications that are currently posted
+ * to the phone. In general, this tracks closely to the list maintained by NotificationManager,
+ * but it can diverge slightly due to lifetime extenders.
+ *
+ * The returned collection is read-only, unsorted, unfiltered, and ungrouped.
+ */
+ public Collection<NotificationEntry> getActiveNotifs() {
+ return mNotifCollection.getActiveNotifs();
+ }
+
+ /**
+ * Registers a listener to be informed when notifications are added, removed or updated.
+ */
+ public void addCollectionListener(NotifCollectionListener listener) {
+ mNotifCollection.addCollectionListener(listener);
+ }
+
+ /**
+ * Registers a lifetime extender. Lifetime extenders can cause notifications that have been
+ * dismissed or retracted to be temporarily retained in the collection.
+ */
+ public void addNotificationLifetimeExtender(NotifLifetimeExtender extender) {
+ mNotifCollection.addNotificationLifetimeExtender(extender);
+ }
+
+ /**
+ * Registers a filter with the pipeline before grouping, promoting and sorting occurs. Filters
+ * are called on each notification in the order that they were registered. If any filter
+ * returns true, the notification is removed from the pipeline (and no other filters are
+ * called on that notif).
+ */
+ public void addPreGroupFilter(NotifFilter filter) {
+ mShadeListBuilder.addPreGroupFilter(filter);
+ }
+
+ /**
+ * Called after notifications have been filtered and after the initial grouping has been
+ * performed but before NotifPromoters have had a chance to promote children out of groups.
+ */
+ public void addOnBeforeTransformGroupsListener(OnBeforeTransformGroupsListener listener) {
+ mShadeListBuilder.addOnBeforeTransformGroupsListener(listener);
+ }
+
+ /**
+ * Registers a promoter with the pipeline. Promoters are able to promote child notifications to
+ * top-level, i.e. move a notification that would be a child of a group and make it appear
+ * ungrouped. Promoters are called on each child notification in the order that they are
+ * registered. If any promoter returns true, the notification is removed from the group (and no
+ * other promoters are called on it).
+ */
+ public void addPromoter(NotifPromoter promoter) {
+ mShadeListBuilder.addPromoter(promoter);
+ }
+
+ /**
+ * Called after notifs have been filtered and groups have been determined but before sections
+ * have been determined or the notifs have been sorted.
+ */
+ public void addOnBeforeSortListener(OnBeforeSortListener listener) {
+ mShadeListBuilder.addOnBeforeSortListener(listener);
+ }
+
+ /**
+ * Assigns sections to each top-level entry, where a section is simply an integer. Sections are
+ * the primary metric by which top-level entries are sorted; NotifComparators are only consulted
+ * when two entries are in the same section. The pipeline doesn't assign any particular meaning
+ * to section IDs -- from it's perspective they're just numbers and it sorts them by a simple
+ * numerical comparison.
+ */
+ public void setSectionsProvider(SectionsProvider provider) {
+ mShadeListBuilder.setSectionsProvider(provider);
+ }
+
+ /**
+ * Comparators that are used to sort top-level entries that share the same section. The
+ * comparators are executed in order until one of them returns a non-zero result. If all return
+ * zero, the pipeline falls back to sorting by rank (and, failing that, Notification.when).
+ */
+ public void setComparators(List<NotifComparator> comparators) {
+ mShadeListBuilder.setComparators(comparators);
+ }
+
+ /**
+ * Registers a filter with the pipeline to filter right before rendering the list (after
+ * pre-group filtering, grouping, promoting and sorting occurs). Filters are
+ * called on each notification in the order that they were registered. If any filter returns
+ * true, the notification is removed from the pipeline (and no other filters are called on that
+ * notif).
+ */
+ public void addPreRenderFilter(NotifFilter filter) {
+ mShadeListBuilder.addPreRenderFilter(filter);
+ }
+
+ /**
+ * Called at the end of the pipeline after the notif list has been finalized but before it has
+ * been handed off to the view layer.
+ */
+ public void addOnBeforeRenderListListener(OnBeforeRenderListListener listener) {
+ mShadeListBuilder.addOnBeforeRenderListListener(listener);
+ }
+
+ /**
+ * Returns a read-only view in to the current shade list, i.e. the list of notifications that
+ * are currently present in the shade. If this method is called during pipeline execution it
+ * will return the current state of the list, which will likely be only partially-generated.
+ */
+ public List<ListEntry> getShadeList() {
+ return mShadeListBuilder.getShadeList();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 7301fe1..2fcfb8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -59,6 +59,7 @@
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGuts;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 19d90f0..76c524b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -32,7 +32,6 @@
import android.annotation.Nullable;
import android.util.ArrayMap;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
@@ -41,6 +40,7 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.SectionsProvider;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
import com.android.systemui.statusbar.notification.logging.NotifEvent;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.util.Assert;
@@ -57,11 +57,13 @@
import javax.inject.Singleton;
/**
- * The implementation of {@link NotifListBuilder}.
+ * The second half of {@link NotifPipeline}. Sits downstream of the NotifCollection and transforms
+ * its "notification set" into the "shade list", the filtered, grouped, and sorted list of
+ * notifications that are currently present in the notification shade.
*/
@MainThread
@Singleton
-public class NotifListBuilderImpl implements NotifListBuilder {
+public class ShadeListBuilder {
private final SystemClock mSystemClock;
private final NotifLog mNotifLog;
@@ -90,7 +92,7 @@
private final List<ListEntry> mReadOnlyNotifList = Collections.unmodifiableList(mNotifList);
@Inject
- public NotifListBuilderImpl(SystemClock systemClock, NotifLog notifLog) {
+ public ShadeListBuilder(SystemClock systemClock, NotifLog notifLog) {
Assert.isMainThread();
mSystemClock = systemClock;
mNotifLog = notifLog;
@@ -116,32 +118,28 @@
mOnRenderListListener = onRenderListListener;
}
- @Override
- public void addOnBeforeTransformGroupsListener(OnBeforeTransformGroupsListener listener) {
+ void addOnBeforeTransformGroupsListener(OnBeforeTransformGroupsListener listener) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
mOnBeforeTransformGroupsListeners.add(listener);
}
- @Override
- public void addOnBeforeSortListener(OnBeforeSortListener listener) {
+ void addOnBeforeSortListener(OnBeforeSortListener listener) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
mOnBeforeSortListeners.add(listener);
}
- @Override
- public void addOnBeforeRenderListListener(OnBeforeRenderListListener listener) {
+ void addOnBeforeRenderListListener(OnBeforeRenderListListener listener) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
mOnBeforeRenderListListeners.add(listener);
}
- @Override
- public void addPreGroupFilter(NotifFilter filter) {
+ void addPreGroupFilter(NotifFilter filter) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
@@ -149,8 +147,7 @@
filter.setInvalidationListener(this::onPreGroupFilterInvalidated);
}
- @Override
- public void addPreRenderFilter(NotifFilter filter) {
+ void addPreRenderFilter(NotifFilter filter) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
@@ -158,8 +155,7 @@
filter.setInvalidationListener(this::onPreRenderFilterInvalidated);
}
- @Override
- public void addPromoter(NotifPromoter promoter) {
+ void addPromoter(NotifPromoter promoter) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
@@ -167,8 +163,7 @@
promoter.setInvalidationListener(this::onPromoterInvalidated);
}
- @Override
- public void setSectionsProvider(SectionsProvider provider) {
+ void setSectionsProvider(SectionsProvider provider) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
@@ -176,8 +171,7 @@
provider.setInvalidationListener(this::onSectionsProviderInvalidated);
}
- @Override
- public void setComparators(List<NotifComparator> comparators) {
+ void setComparators(List<NotifComparator> comparators) {
Assert.isMainThread();
mPipelineState.requireState(STATE_IDLE);
@@ -188,8 +182,7 @@
}
}
- @Override
- public List<ListEntry> getActiveNotifs() {
+ List<ListEntry> getShadeList() {
Assert.isMainThread();
return mReadOnlyNotifList;
}
@@ -275,7 +268,7 @@
}
/**
- * The core algorithm of the pipeline. See the top comment in {@link NotifListBuilder} for
+ * The core algorithm of the pipeline. See the top comment in {@link NotifPipeline} for
* details on our contracts with other code.
*
* Once the build starts we are very careful to protect against reentrant code. Anything that
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CoalescedEvent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/CoalescedEvent.kt
similarity index 87%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CoalescedEvent.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/CoalescedEvent.kt
index b6218b4..143de8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CoalescedEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/CoalescedEvent.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection.notifcollection
+package com.android.systemui.statusbar.notification.collection.coalescer
import android.service.notification.NotificationListenerService.Ranking
import android.service.notification.StatusBarNotification
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/EventBatch.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/EventBatch.java
similarity index 89%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/EventBatch.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/EventBatch.java
index ac51178..2c6a165 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/EventBatch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/EventBatch.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection.notifcollection;
+package com.android.systemui.statusbar.notification.collection.coalescer;
import java.util.ArrayList;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescer.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
index c3e3c53..8076616 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection.notifcollection;
+package com.android.systemui.statusbar.notification.collection.coalescer;
import static com.android.systemui.statusbar.notification.logging.NotifEvent.COALESCED_EVENT;
import static com.android.systemui.statusbar.notification.logging.NotifEvent.EARLY_BATCH_EMIT;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java
index 898918e..c1a11b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java
@@ -16,27 +16,16 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
-import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
-import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
/**
- * Interface for registering callbacks to the {@link NewNotifPipeline}.
- *
- * This includes registering:
- * {@link Pluggable}s to the {@link NotifListBuilder}
- * {@link NotifCollectionListener}s and {@link NotifLifetimeExtender}s to {@link NotifCollection}
+ * Interface for registering callbacks to the {@link NotifPipeline}.
*/
public interface Coordinator {
-
/**
* Called after the NewNotifPipeline is initialized.
- * Coordinators should register their {@link Pluggable}s to the notifListBuilder
- * and their {@link NotifCollectionListener}s and {@link NotifLifetimeExtender}s
- * to the notifCollection in this method.
+ * Coordinators should register their listeners and {@link Pluggable}s to the pipeline.
*/
- void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder);
+ void attach(NotifPipeline pipeline);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
index 5e7dd98..625d1b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
@@ -23,9 +23,8 @@
import android.os.RemoteException;
import android.service.notification.StatusBarNotification;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -52,10 +51,10 @@
}
@Override
- public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+ public void attach(NotifPipeline pipeline) {
mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
- notifListBuilder.addPreGroupFilter(mNotifFilter);
+ pipeline.addPreGroupFilter(mNotifFilter);
}
private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
index 62342b1..da119c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
@@ -25,12 +25,11 @@
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
-import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import java.util.HashMap;
import java.util.Map;
@@ -57,7 +56,7 @@
private final AppOpsController mAppOpsController;
private final Handler mMainHandler;
- private NotifCollection mNotifCollection;
+ private NotifPipeline mNotifPipeline;
@Inject
public ForegroundCoordinator(
@@ -70,20 +69,20 @@
}
@Override
- public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
- mNotifCollection = notifCollection;
+ public void attach(NotifPipeline pipeline) {
+ mNotifPipeline = pipeline;
// extend the lifetime of foreground notification services to show for at least 5 seconds
- mNotifCollection.addNotificationLifetimeExtender(mForegroundLifetimeExtender);
+ mNotifPipeline.addNotificationLifetimeExtender(mForegroundLifetimeExtender);
// listen for new notifications to add appOps
- mNotifCollection.addCollectionListener(mNotifCollectionListener);
+ mNotifPipeline.addCollectionListener(mNotifCollectionListener);
// when appOps change, update any relevant notifications to update appOps for
mAppOpsController.addCallback(ForegroundServiceController.APP_OPS, this::onAppOpsChanged);
// filter out foreground service notifications that aren't necessary anymore
- notifListBuilder.addPreGroupFilter(mNotifFilter);
+ mNotifPipeline.addPreGroupFilter(mNotifFilter);
}
/**
@@ -230,7 +229,7 @@
}
private NotificationEntry findNotificationEntryWithKey(String key) {
- for (NotificationEntry entry : mNotifCollection.getNotifs()) {
+ for (NotificationEntry entry : mNotifPipeline.getActiveNotifs()) {
if (entry.getKey().equals(key)) {
return entry;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
index db107f5..a26ee545 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
@@ -39,9 +39,8 @@
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -86,9 +85,9 @@
}
@Override
- public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+ public void attach(NotifPipeline pipeline) {
setupInvalidateNotifListCallbacks();
- notifListBuilder.addPreRenderFilter(mNotifFilter);
+ pipeline.addPreRenderFilter(mNotifFilter);
}
private final NotifFilter mNotifFilter = new NotifFilter(TAG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
index 2436bb9..562a618 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
@@ -18,11 +18,10 @@
import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.FeatureFlags;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
-import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -33,8 +32,8 @@
import javax.inject.Singleton;
/**
- * Handles the attachment of the {@link NotifListBuilder} and {@link NotifCollection} to the
- * {@link Coordinator}s, so that the Coordinators can register their respective callbacks.
+ * Handles the attachment of {@link Coordinator}s to the {@link NotifPipeline} so that the
+ * Coordinators can register their respective callbacks.
*/
@Singleton
public class NotifCoordinators implements Dumpable {
@@ -63,14 +62,12 @@
}
/**
- * Sends the initialized notifListBuilder and notifCollection to each
- * coordinator to indicate the notifListBuilder is ready to accept {@link Pluggable}s
- * and the notifCollection is ready to accept {@link NotifCollectionListener}s and
- * {@link NotifLifetimeExtender}s.
+ * Sends the pipeline to each coordinator when the pipeline is ready to accept
+ * {@link Pluggable}s, {@link NotifCollectionListener}s and {@link NotifLifetimeExtender}s.
*/
- public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+ public void attach(NotifPipeline pipeline) {
for (Coordinator c : mCoordinators) {
- c.attach(notifCollection, notifListBuilder);
+ c.attach(pipeline);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
index a14f0e1..20c9cbc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
@@ -16,13 +16,12 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
-import com.android.systemui.statusbar.notification.collection.NotifInflater;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.logging.NotifEvent;
import com.android.systemui.statusbar.notification.logging.NotifLog;
@@ -55,10 +54,10 @@
}
@Override
- public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
- notifCollection.addCollectionListener(mNotifCollectionListener);
- notifListBuilder.addPreRenderFilter(mNotifInflationErrorFilter);
- notifListBuilder.addPreRenderFilter(mNotifInflatingFilter);
+ public void attach(NotifPipeline pipeline) {
+ pipeline.addCollectionListener(mNotifCollectionListener);
+ pipeline.addPreRenderFilter(mNotifInflationErrorFilter);
+ pipeline.addPreRenderFilter(mNotifInflatingFilter);
}
private final NotifCollectionListener mNotifCollectionListener = new NotifCollectionListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
index 0751aa8..7e9e760 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
@@ -17,9 +17,8 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import javax.inject.Inject;
@@ -43,10 +42,10 @@
}
@Override
- public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+ public void attach(NotifPipeline pipeline) {
mStatusBarStateController.addCallback(mStatusBarStateCallback);
- notifListBuilder.addPreGroupFilter(mNotifFilter);
+ pipeline.addPreGroupFilter(mNotifFilter);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.java
similarity index 92%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflater.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.java
index fc04827..ea0ece4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.java
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.inflation;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.coordinator.PreparationCoordinator;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
similarity index 90%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinder.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
index 7504e86..3f500644 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.inflation;
import android.annotation.Nullable;
import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
/**
* Used by the {@link NotificationEntryManager}. When notifications are added or updated, the binder
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index 80b5b8a..1ab20a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.inflation;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
@@ -39,6 +39,7 @@
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/FakePipelineConsumer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/FakePipelineConsumer.java
index 986ee17..15f312d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/FakePipelineConsumer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/FakePipelineConsumer.java
@@ -19,8 +19,8 @@
import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -36,7 +36,7 @@
private List<ListEntry> mEntries = Collections.emptyList();
/** Attach the consumer to the pipeline. */
- public void attach(NotifListBuilderImpl listBuilder) {
+ public void attach(ShadeListBuilder listBuilder) {
listBuilder.setOnRenderListListener(this::onBuildComplete);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
similarity index 78%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
index 8d3d0ff..959b002 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
@@ -24,10 +24,11 @@
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
+import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators;
-import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -39,10 +40,11 @@
* Initialization code for the new notification pipeline.
*/
@Singleton
-public class NewNotifPipeline implements Dumpable {
+public class NotifPipelineInitializer implements Dumpable {
+ private final NotifPipeline mPipelineWrapper;
private final GroupCoalescer mGroupCoalescer;
private final NotifCollection mNotifCollection;
- private final NotifListBuilderImpl mNotifPipeline;
+ private final ShadeListBuilder mListBuilder;
private final NotifCoordinators mNotifPluggableCoordinators;
private final NotifInflaterImpl mNotifInflater;
private final DumpController mDumpController;
@@ -51,17 +53,19 @@
private final FakePipelineConsumer mFakePipelineConsumer = new FakePipelineConsumer();
@Inject
- public NewNotifPipeline(
+ public NotifPipelineInitializer(
+ NotifPipeline pipelineWrapper,
GroupCoalescer groupCoalescer,
NotifCollection notifCollection,
- NotifListBuilderImpl notifPipeline,
+ ShadeListBuilder listBuilder,
NotifCoordinators notifCoordinators,
NotifInflaterImpl notifInflater,
DumpController dumpController,
FeatureFlags featureFlags) {
+ mPipelineWrapper = pipelineWrapper;
mGroupCoalescer = groupCoalescer;
mNotifCollection = notifCollection;
- mNotifPipeline = notifPipeline;
+ mListBuilder = listBuilder;
mNotifPluggableCoordinators = notifCoordinators;
mDumpController = dumpController;
mNotifInflater = notifInflater;
@@ -81,11 +85,11 @@
}
// Wire up coordinators
- mFakePipelineConsumer.attach(mNotifPipeline);
- mNotifPluggableCoordinators.attach(mNotifCollection, mNotifPipeline);
+ mNotifPluggableCoordinators.attach(mPipelineWrapper);
// Wire up pipeline
- mNotifPipeline.attach(mNotifCollection);
+ mFakePipelineConsumer.attach(mListBuilder);
+ mListBuilder.attach(mNotifCollection);
mNotifCollection.attach(mGroupCoalescer);
mGroupCoalescer.attach(notificationService);
@@ -99,5 +103,5 @@
mGroupCoalescer.dump(fd, pw, args);
}
- private static final String TAG = "NewNotifPipeline";
+ private static final String TAG = "NotifPipeline";
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifListBuilder.java
deleted file mode 100644
index 7580924..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifListBuilder.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2019 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.statusbar.notification.collection.listbuilder;
-
-import com.android.systemui.statusbar.notification.collection.ListEntry;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator;
-import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
-import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
-import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.SectionsProvider;
-
-import java.util.List;
-
-/**
- * The system that constructs the current "notification list", the list of notifications that are
- * currently being displayed to the user.
- *
- * The pipeline proceeds through a series of stages in order to produce the final list (see below).
- * Each stage exposes hooks and listeners for other code to participate.
- *
- * This list differs from the canonical one we receive from system server in a few ways:
- * - Filtered: Some notifications are filtered out. For example, we filter out notifications whose
- * views haven't been inflated yet. We also filter out some notifications if we're on the lock
- * screen. To participate, see {@link #addFilter(NotifFilter)}.
- * - Grouped: Notifications that are part of the same group are clustered together into a single
- * GroupEntry. These groups are then transformed in order to remove children or completely split
- * them apart. To participate, see {@link #addPromoter(NotifPromoter)}.
- * - Sorted: All top-level notifications are sorted. To participate, see
- * {@link #setSectionsProvider(SectionsProvider)} and {@link #setComparators(List)}
- *
- * The exact order of all hooks is as follows:
- * 0. Collection listeners are fired (see {@link NotifCollection}).
- * 1. NotifFilters are called on each notification currently in NotifCollection.
- * 2. Initial grouping is performed (NotificationEntries will have their parents set
- * appropriately).
- * 3. OnBeforeTransformGroupListeners are fired
- * 4. NotifPromoters are called on each notification with a parent
- * 5. OnBeforeSortListeners are fired
- * 6. SectionsProvider is called on each top-level entry in the list
- * 7. The top-level entries are sorted using the provided NotifComparators (plus some additional
- * built-in logic).
- * 8. OnBeforeRenderListListeners are fired
- * 9. The list is handed off to the view layer to be rendered.
- */
-public interface NotifListBuilder {
-
- /**
- * Registers a filter with the pipeline before grouping, promoting and sorting occurs. Filters
- * are called on each notification in the order that they were registered. If any filter
- * returns true, the notification is removed from the pipeline (and no other filters are
- * called on that notif).
- */
- void addPreGroupFilter(NotifFilter filter);
-
- /**
- * Registers a promoter with the pipeline. Promoters are able to promote child notifications to
- * top-level, i.e. move a notification that would be a child of a group and make it appear
- * ungrouped. Promoters are called on each child notification in the order that they are
- * registered. If any promoter returns true, the notification is removed from the group (and no
- * other promoters are called on it).
- */
- void addPromoter(NotifPromoter promoter);
-
- /**
- * Assigns sections to each top-level entry, where a section is simply an integer. Sections are
- * the primary metric by which top-level entries are sorted; NotifComparators are only consulted
- * when two entries are in the same section. The pipeline doesn't assign any particular meaning
- * to section IDs -- from it's perspective they're just numbers and it sorts them by a simple
- * numerical comparison.
- */
- void setSectionsProvider(SectionsProvider provider);
-
- /**
- * Comparators that are used to sort top-level entries that share the same section. The
- * comparators are executed in order until one of them returns a non-zero result. If all return
- * zero, the pipeline falls back to sorting by rank (and, failing that, Notification.when).
- */
- void setComparators(List<NotifComparator> comparators);
-
- /**
- * Registers a filter with the pipeline to filter right before rendering the list (after
- * pre-group filtering, grouping, promoting and sorting occurs). Filters are
- * called on each notification in the order that they were registered. If any filter returns
- * true, the notification is removed from the pipeline (and no other filters are called on that
- * notif).
- */
- void addPreRenderFilter(NotifFilter filter);
-
- /**
- * Called after notifications have been filtered and after the initial grouping has been
- * performed but before NotifPromoters have had a chance to promote children out of groups.
- */
- void addOnBeforeTransformGroupsListener(OnBeforeTransformGroupsListener listener);
-
- /**
- * Called after notifs have been filtered and groups have been determined but before sections
- * have been determined or the notifs have been sorted.
- */
- void addOnBeforeSortListener(OnBeforeSortListener listener);
-
- /**
- * Called at the end of the pipeline after the notif list has been finalized but before it has
- * been handed off to the view layer.
- */
- void addOnBeforeRenderListListener(OnBeforeRenderListListener listener);
-
- /**
- * Returns a read-only view in to the current notification list. If this method is called
- * during pipeline execution it will return the current state of the list, which will likely
- * be only partially-generated.
- */
- List<ListEntry> getActiveNotifs();
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java
index f6ca12d..44a27a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeRenderListListener.java
@@ -17,10 +17,11 @@
package com.android.systemui.statusbar.notification.collection.listbuilder;
import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import java.util.List;
-/** See {@link NotifListBuilder#addOnBeforeRenderListListener(OnBeforeRenderListListener)} */
+/** See {@link NotifPipeline#addOnBeforeRenderListListener(OnBeforeRenderListListener)} */
public interface OnBeforeRenderListListener {
/**
* Called at the end of the pipeline after the notif list has been finalized but before it has
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java
index 7be7ac0..56cfe5c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeSortListener.java
@@ -17,10 +17,11 @@
package com.android.systemui.statusbar.notification.collection.listbuilder;
import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import java.util.List;
-/** See {@link NotifListBuilder#addOnBeforeSortListener(OnBeforeSortListener)} */
+/** See {@link NotifPipeline#addOnBeforeSortListener(OnBeforeSortListener)} */
public interface OnBeforeSortListener {
/**
* Called after the notif list has been filtered and grouped but before sections have been
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java
index d7a0815..0dc4df0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeTransformGroupsListener.java
@@ -17,13 +17,14 @@
package com.android.systemui.statusbar.notification.collection.listbuilder;
import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
import java.util.List;
/**
* See
- * {@link NotifListBuilder#addOnBeforeTransformGroupsListener(OnBeforeTransformGroupsListener)}
+ * {@link NotifPipeline#addOnBeforeTransformGroupsListener(OnBeforeTransformGroupsListener)}
*/
public interface OnBeforeTransformGroupsListener {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java
index 084d038..1897ba2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java
@@ -18,13 +18,13 @@
import android.annotation.IntDef;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
+import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
- * Used by {@link NotifListBuilderImpl} to track its internal state machine.
+ * Used by {@link ShadeListBuilder} to track its internal state machine.
*/
public class PipelineState {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java
index a191c83..0d150ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifComparator.java
@@ -17,13 +17,13 @@
package com.android.systemui.statusbar.notification.collection.listbuilder.pluggable;
import com.android.systemui.statusbar.notification.collection.ListEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import java.util.Comparator;
import java.util.List;
/**
- * Pluggable for participating in notif sorting. See {@link NotifListBuilder#setComparators(List)}.
+ * Pluggable for participating in notif sorting. See {@link NotifPipeline#setComparators(List)}.
*/
public abstract class NotifComparator
extends Pluggable<NotifComparator>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java
index e6189ed..8f575cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java
@@ -16,12 +16,12 @@
package com.android.systemui.statusbar.notification.collection.listbuilder.pluggable;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
/**
* Pluggable for participating in notif filtering.
- * See {@link NotifListBuilder#addPreGroupFilter} and {@link NotifListBuilder#addPreRenderFilter}.
+ * See {@link NotifPipeline#addPreGroupFilter} and {@link NotifPipeline#addPreRenderFilter}.
*/
public abstract class NotifFilter extends Pluggable<NotifFilter> {
protected NotifFilter(String name) {
@@ -35,9 +35,9 @@
* however. If another filter returns true before yours, we'll skip straight to the next notif.
*
* @param entry The entry in question.
- * If this filter is registered via {@link NotifListBuilder#addPreGroupFilter},
+ * If this filter is registered via {@link NotifPipeline#addPreGroupFilter},
* this entry will not have any grouping nor sorting information.
- * If this filter is registered via {@link NotifListBuilder#addPreRenderFilter},
+ * If this filter is registered via {@link NotifPipeline#addPreRenderFilter},
* this entry will have grouping and sorting information.
* @param now A timestamp in SystemClock.uptimeMillis that represents "now" for the purposes of
* pipeline execution. This value will be the same for all pluggable calls made
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifPromoter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifPromoter.java
index 84e16f4..5fce446 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifPromoter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifPromoter.java
@@ -16,13 +16,13 @@
package com.android.systemui.statusbar.notification.collection.listbuilder.pluggable;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
/**
* Pluggable for participating in notif promotion. Notif promoters can upgrade notifications
* from being children of a group to top-level notifications. See
- * {@link NotifListBuilder#addPromoter(NotifPromoter)}.
+ * {@link NotifPipeline#addPromoter}.
*/
public abstract class NotifPromoter extends Pluggable<NotifPromoter> {
protected NotifPromoter(String name) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
index f9ce197..4270408 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
@@ -18,10 +18,10 @@
import android.annotation.Nullable;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
/**
- * Generic superclass for chunks of code that can plug into the {@link NotifListBuilder}.
+ * Generic superclass for chunks of code that can plug into the {@link NotifPipeline}.
*
* A pluggable is fundamentally three things:
* 1. A name (for debugging purposes)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/CollectionReadyForBuildListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CollectionReadyForBuildListener.java
similarity index 82%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/CollectionReadyForBuildListener.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CollectionReadyForBuildListener.java
index 87aaea0..4023474 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/CollectionReadyForBuildListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/CollectionReadyForBuildListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.notifcollection;
+
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import java.util.Collection;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/DismissedByUserStats.java
similarity index 91%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/DismissedByUserStats.java
index ecce6ea..b268686 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/DismissedByUserStats.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/DismissedByUserStats.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.notifcollection;
import android.service.notification.NotificationStats.DismissalSentiment;
import android.service.notification.NotificationStats.DismissalSurface;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
similarity index 71%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
index 032620e..9cbc7d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,9 +14,11 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.notifcollection;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
/**
* Listener interface for {@link NotifCollection}.
@@ -36,7 +38,9 @@
}
/**
- * Called immediately after a notification has been removed from the collection.
+ * Called whenever a notification is retracted by system server. This method is not called
+ * immediately after a user dismisses a notification: we wait until we receive confirmation from
+ * system server before considering the notification removed.
*/
default void onEntryRemoved(
NotificationEntry entry,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifLifetimeExtender.java
similarity index 89%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifLifetimeExtender.java
index 2c7b138..05f5ea8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLifetimeExtender.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifLifetimeExtender.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,9 +14,11 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection;
+package com.android.systemui.statusbar.notification.collection.notifcollection;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
/**
* A way for other code to temporarily extend the lifetime of a notification after it has been
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
index c6c36ee..02acc81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotifEvent.java
@@ -22,8 +22,8 @@
import com.android.systemui.log.RichEvent;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
-import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer;
+import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
+import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -67,7 +67,7 @@
}
/**
- * @return if this event occurred in {@link NotifListBuilder}
+ * @return if this event occurred in {@link ShadeListBuilder}
*/
static boolean isListBuilderEvent(@EventType int type) {
return isBetweenInclusive(type, 0, TOTAL_LIST_BUILDER_EVENT_TYPES);
@@ -161,7 +161,7 @@
private static final int TOTAL_EVENT_LABELS = EVENT_LABELS.length;
/**
- * Events related to {@link NotifListBuilder}
+ * Events related to {@link ShadeListBuilder}
*/
public static final int WARN = 0;
public static final int ON_BUILD_LIST = 1;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 189d3b6..ba70cf4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -199,8 +199,8 @@
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -364,7 +364,7 @@
private final HeadsUpManagerPhone mHeadsUpManager;
private final DynamicPrivacyController mDynamicPrivacyController;
private final BypassHeadsUpNotifier mBypassHeadsUpNotifier;
- private final Lazy<NewNotifPipeline> mNewNotifPipeline;
+ private final Lazy<NotifPipelineInitializer> mNewNotifPipeline;
private final FalsingManager mFalsingManager;
private final BroadcastDispatcher mBroadcastDispatcher;
private final ConfigurationController mConfigurationController;
@@ -625,7 +625,7 @@
HeadsUpManagerPhone headsUpManagerPhone,
DynamicPrivacyController dynamicPrivacyController,
BypassHeadsUpNotifier bypassHeadsUpNotifier,
- Lazy<NewNotifPipeline> newNotifPipeline,
+ Lazy<NotifPipelineInitializer> newNotifPipeline,
FalsingManager falsingManager,
BroadcastDispatcher broadcastDispatcher,
RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
index be7f0a0..b4d5dad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
@@ -65,8 +65,8 @@
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
@@ -117,7 +117,7 @@
HeadsUpManagerPhone headsUpManagerPhone,
DynamicPrivacyController dynamicPrivacyController,
BypassHeadsUpNotifier bypassHeadsUpNotifier,
- Lazy<NewNotifPipeline> newNotifPipeline,
+ Lazy<NotifPipelineInitializer> newNotifPipeline,
FalsingManager falsingManager,
BroadcastDispatcher broadcastDispatcher,
RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 12a6516..720f229 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -66,7 +66,7 @@
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index 9c9a627..8d11b54 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -48,7 +48,7 @@
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -71,7 +71,7 @@
@Mock private NotificationEntryManager mEntryManager;
@Mock private AppOpsController mAppOpsController;
@Mock private Handler mMainHandler;
- @Mock private NotifCollection mNotifCollection;
+ @Mock private NotifPipeline mNotifPipeline;
@Before
public void setUp() throws Exception {
@@ -81,7 +81,7 @@
MockitoAnnotations.initMocks(this);
mFsc = new ForegroundServiceController(mEntryManager, mAppOpsController, mMainHandler);
mListener = new ForegroundServiceNotificationListener(
- mContext, mFsc, mEntryManager, mNotifCollection);
+ mContext, mFsc, mEntryManager, mNotifPipeline);
ArgumentCaptor<NotificationEntryListener> entryListenerCaptor =
ArgumentCaptor.forClass(NotificationEntryListener.class);
verify(mEntryManager).addNotificationEntryListener(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 1e0179d..cc5514f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -78,7 +78,7 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt
index bf84f2b..29ce920 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt
@@ -21,7 +21,7 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinder
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder
import com.android.systemui.statusbar.notification.logging.NotifLog
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index 28feaca..09cc5ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -52,9 +52,13 @@
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
-import com.android.systemui.statusbar.notification.collection.notifcollection.CoalescedEvent;
-import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer;
-import com.android.systemui.statusbar.notification.collection.notifcollection.GroupCoalescer.BatchableNotificationHandler;
+import com.android.systemui.statusbar.notification.collection.coalescer.CoalescedEvent;
+import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
+import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer.BatchableNotificationHandler;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import com.android.systemui.util.Assert;
import org.junit.Before;
@@ -377,7 +381,7 @@
verify(mExtender3).shouldExtendLifetime(entry2, REASON_UNKNOWN);
// THEN the entry is not removed
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
// THEN the entry properly records all extenders that returned true
assertEquals(Arrays.asList(mExtender1, mExtender2), entry2.mLifetimeExtenders);
@@ -398,7 +402,7 @@
// GIVEN a notification gets lifetime-extended by one of them
mNoMan.retractNotif(notif2.sbn, REASON_APP_CANCEL);
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
clearInvocations(mExtender1, mExtender2, mExtender3);
// WHEN the last active extender expires (but new ones become active)
@@ -413,7 +417,7 @@
verify(mExtender3).shouldExtendLifetime(entry2, REASON_UNKNOWN);
// THEN the entry is not removed
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
// THEN the entry properly records all extenders that returned true
assertEquals(Arrays.asList(mExtender1, mExtender3), entry2.mLifetimeExtenders);
@@ -435,7 +439,7 @@
// GIVEN a notification gets lifetime-extended by a couple of them
mNoMan.retractNotif(notif2.sbn, REASON_APP_CANCEL);
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
clearInvocations(mExtender1, mExtender2, mExtender3);
// WHEN one (but not all) of the extenders expires
@@ -443,7 +447,7 @@
mExtender2.callback.onEndLifetimeExtension(mExtender2, entry2);
// THEN the entry is not removed
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
// THEN we don't re-query the extenders
verify(mExtender1, never()).shouldExtendLifetime(eq(entry2), anyInt());
@@ -470,7 +474,7 @@
// GIVEN a notification gets lifetime-extended by a couple of them
mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
clearInvocations(mExtender1, mExtender2, mExtender3);
// WHEN all of the active extenders expire
@@ -480,7 +484,7 @@
mExtender1.callback.onEndLifetimeExtension(mExtender1, entry2);
// THEN the entry removed
- assertFalse(mCollection.getNotifs().contains(entry2));
+ assertFalse(mCollection.getActiveNotifs().contains(entry2));
verify(mCollectionListener).onEntryRemoved(entry2, REASON_UNKNOWN, false);
}
@@ -500,7 +504,7 @@
// GIVEN a notification gets lifetime-extended by a couple of them
mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
clearInvocations(mExtender1, mExtender2, mExtender3);
// WHEN the notification is reposted
@@ -511,7 +515,7 @@
verify(mExtender2).cancelLifetimeExtension(entry2);
// THEN the notification is still present
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
}
@Test(expected = IllegalStateException.class)
@@ -530,7 +534,7 @@
// GIVEN a notification gets lifetime-extended by a couple of them
mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
clearInvocations(mExtender1, mExtender2, mExtender3);
// WHEN a lifetime extender makes a reentrant call during cancelLifetimeExtension()
@@ -559,7 +563,7 @@
// GIVEN a notification gets lifetime-extended by a couple of them
mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
- assertTrue(mCollection.getNotifs().contains(entry2));
+ assertTrue(mCollection.getActiveNotifs().contains(entry2));
clearInvocations(mExtender1, mExtender2, mExtender3);
// WHEN the notification is reposted
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
similarity index 98%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index 3e4068b..be06748 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -38,7 +38,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl.OnRenderListListener;
+import com.android.systemui.statusbar.notification.collection.ShadeListBuilder.OnRenderListListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
@@ -46,6 +46,7 @@
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.SectionsProvider;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.util.Assert;
import com.android.systemui.util.time.FakeSystemClock;
@@ -72,9 +73,9 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-public class NotifListBuilderImplTest extends SysuiTestCase {
+public class ShadeListBuilderTest extends SysuiTestCase {
- private NotifListBuilderImpl mListBuilder;
+ private ShadeListBuilder mListBuilder;
private FakeSystemClock mSystemClock = new FakeSystemClock();
@Mock private NotifLog mNotifLog;
@@ -99,7 +100,7 @@
MockitoAnnotations.initMocks(this);
Assert.sMainLooper = TestableLooper.get(this).getLooper();
- mListBuilder = new NotifListBuilderImpl(mSystemClock, mNotifLog);
+ mListBuilder = new ShadeListBuilder(mSystemClock, mNotifLog);
mListBuilder.setOnRenderListListener(mOnRenderListListener);
mListBuilder.attach(mNotifCollection);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
similarity index 98%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescerTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
index 7ff3240..5e0baf2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/GroupCoalescerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection.notifcollection;
+package com.android.systemui.statusbar.notification.collection.coalescer;
import static com.android.internal.util.Preconditions.checkNotNull;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
index ea6c70a..701cf95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
@@ -36,7 +36,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.RankingBuilder;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
@@ -65,7 +65,7 @@
@Mock private ActivityManagerInternal mActivityMangerInternal;
@Mock private IPackageManager mIPackageManager;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
- @Mock private NotifListBuilderImpl mNotifListBuilder;
+ @Mock private NotifPipeline mNotifPipeline;
private Notification mNotification;
private NotificationEntry mEntry;
private DeviceProvisionedCoordinator mDeviceProvisionedCoordinator;
@@ -84,8 +84,8 @@
.build();
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
- mDeviceProvisionedCoordinator.attach(null, mNotifListBuilder);
- verify(mNotifListBuilder, times(1)).addPreGroupFilter(filterCaptor.capture());
+ mDeviceProvisionedCoordinator.attach(mNotifPipeline);
+ verify(mNotifPipeline, times(1)).addPreGroupFilter(filterCaptor.capture());
mDeviceProvisionedFilter = filterCaptor.getValue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
index 01bca0d..6cc8dd9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
@@ -36,12 +36,11 @@
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.statusbar.notification.collection.NotifCollection;
-import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import org.junit.Before;
import org.junit.Test;
@@ -59,8 +58,7 @@
@Mock private Handler mMainHandler;
@Mock private ForegroundServiceController mForegroundServiceController;
@Mock private AppOpsController mAppOpsController;
- @Mock private NotifListBuilderImpl mNotifListBuilder;
- @Mock private NotifCollection mNotifCollection;
+ @Mock private NotifPipeline mNotifPipeline;
private NotificationEntry mEntry;
private Notification mNotification;
@@ -84,9 +82,9 @@
ArgumentCaptor<NotifLifetimeExtender> lifetimeExtenderCaptor =
ArgumentCaptor.forClass(NotifLifetimeExtender.class);
- mForegroundCoordinator.attach(mNotifCollection, mNotifListBuilder);
- verify(mNotifListBuilder, times(1)).addPreGroupFilter(filterCaptor.capture());
- verify(mNotifCollection, times(1)).addNotificationLifetimeExtender(
+ mForegroundCoordinator.attach(mNotifPipeline);
+ verify(mNotifPipeline, times(1)).addPreGroupFilter(filterCaptor.capture());
+ verify(mNotifPipeline, times(1)).addNotificationLifetimeExtender(
lifetimeExtenderCaptor.capture());
mForegroundFilter = filterCaptor.getValue();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
index f921cf9..5866d90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
@@ -41,7 +41,7 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
@@ -68,7 +68,7 @@
@Mock private StatusBarStateController mStatusBarStateController;
@Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@Mock private HighPriorityProvider mHighPriorityProvider;
- @Mock private NotifListBuilderImpl mNotifListBuilder;
+ @Mock private NotifPipeline mNotifPipeline;
private NotificationEntry mEntry;
private KeyguardCoordinator mKeyguardCoordinator;
@@ -87,8 +87,8 @@
.build();
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
- mKeyguardCoordinator.attach(null, mNotifListBuilder);
- verify(mNotifListBuilder, times(1)).addPreRenderFilter(filterCaptor.capture());
+ mKeyguardCoordinator.attach(mNotifPipeline);
+ verify(mNotifPipeline, times(1)).addPreRenderFilter(filterCaptor.capture());
mKeyguardFilter = filterCaptor.getValue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
index d3b16c3..e84f9cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
@@ -33,7 +33,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.RankingBuilder;
-import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
@@ -50,7 +50,7 @@
public class RankingCoordinatorTest extends SysuiTestCase {
@Mock private StatusBarStateController mStatusBarStateController;
- @Mock private NotifListBuilderImpl mNotifListBuilder;
+ @Mock private NotifPipeline mNotifPipeline;
private NotificationEntry mEntry;
private RankingCoordinator mRankingCoordinator;
private NotifFilter mRankingFilter;
@@ -62,8 +62,8 @@
mEntry = new NotificationEntryBuilder().build();
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
- mRankingCoordinator.attach(null, mNotifListBuilder);
- verify(mNotifListBuilder, times(1)).addPreGroupFilter(filterCaptor.capture());
+ mRankingCoordinator.attach(mNotifPipeline);
+ verify(mNotifPipeline, times(1)).addPreGroupFilter(filterCaptor.capture());
mRankingFilter = filterCaptor.getValue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 9bd3914..d9939f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -71,7 +71,7 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 5ac7bfb..782e14c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -54,7 +54,7 @@
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 560aadb..fee4852 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -120,8 +120,8 @@
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
@@ -214,7 +214,7 @@
@Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
@Mock private KeyguardBypassController mKeyguardBypassController;
@Mock private DynamicPrivacyController mDynamicPrivacyController;
- @Mock private NewNotifPipeline mNewNotifPipeline;
+ @Mock private NotifPipelineInitializer mNewNotifPipeline;
@Mock private ZenModeController mZenModeController;
@Mock private AutoHideController mAutoHideController;
@Mock private NotificationViewHierarchyManager mNotificationViewHierarchyManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 4103d71..cd89d3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -30,12 +30,12 @@
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
-import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.settingslib.graph.SignalDrawable;
import com.android.settingslib.net.DataUsageController;
@@ -418,7 +418,7 @@
intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn);
intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, mSubId);
+ SubscriptionManager.putSubscriptionIdExtra(intent, mSubId);
return intent;
}
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index e1fe3bf..900c671 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -501,13 +501,15 @@
p2pInfo.groupFormed = isGroupFormed;
p2pInfo.isGroupOwner = isGroupOwner;
- WifiP2pGroup group = new WifiP2pGroup();
- group.setIsGroupOwner(isGroupOwner);
- group.setInterface(ifname);
+ WifiP2pGroup group = mock(WifiP2pGroup.class);
+ when(group.isGroupOwner()).thenReturn(isGroupOwner);
+ when(group.getInterface()).thenReturn(ifname);
- final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
- intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, p2pInfo);
- intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, group);
+ final Intent intent = mock(Intent.class);
+ when(intent.getAction()).thenReturn(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
+ when(intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO)).thenReturn(p2pInfo);
+ when(intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP)).thenReturn(group);
+
mServiceContext.sendBroadcastAsUserMultiplePermissions(intent, UserHandle.ALL,
P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST);
}
diff --git a/services/backup/java/com/android/server/backup/internal/BackupHandler.java b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
index eb62620..b06fc52 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupHandler.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
@@ -21,12 +21,10 @@
import static com.android.server.backup.BackupManagerService.TAG;
import android.app.backup.RestoreSet;
-import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.EventLog;
import android.util.Pair;
import android.util.Slog;
@@ -40,7 +38,6 @@
import com.android.server.backup.TransportManager;
import com.android.server.backup.UserBackupManagerService;
import com.android.server.backup.fullbackup.PerformAdbBackupTask;
-import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
import com.android.server.backup.keyvalue.BackupRequest;
import com.android.server.backup.keyvalue.KeyValueBackupTask;
import com.android.server.backup.params.AdbBackupParams;
@@ -73,10 +70,7 @@
public static final int MSG_RESTORE_SESSION_TIMEOUT = 8;
public static final int MSG_FULL_CONFIRMATION_TIMEOUT = 9;
public static final int MSG_RUN_ADB_RESTORE = 10;
- public static final int MSG_RETRY_INIT = 11;
public static final int MSG_RETRY_CLEAR = 12;
- public static final int MSG_WIDGET_BROADCAST = 13;
- public static final int MSG_RUN_FULL_TRANSPORT_BACKUP = 14;
public static final int MSG_REQUEST_BACKUP = 15;
public static final int MSG_SCHEDULE_BACKUP_PACKAGE = 16;
public static final int MSG_BACKUP_OPERATION_TIMEOUT = 17;
@@ -279,12 +273,6 @@
break;
}
- case MSG_RUN_FULL_TRANSPORT_BACKUP: {
- PerformFullTransportBackupTask task = (PerformFullTransportBackupTask) msg.obj;
- (new Thread(task, "transport-backup")).start();
- break;
- }
-
case MSG_RUN_RESTORE: {
RestoreParams params = (RestoreParams) msg.obj;
Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
@@ -445,12 +433,6 @@
break;
}
- case MSG_WIDGET_BROADCAST: {
- final Intent intent = (Intent) msg.obj;
- backupManagerService.getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
- break;
- }
-
case MSG_REQUEST_BACKUP: {
BackupParams params = (BackupParams) msg.obj;
if (MORE_DEBUG) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f4962e5..5435cba 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -5505,7 +5505,10 @@
// changes that would conflict throughout the automerger graph. Having this method temporarily
// helps with the process of going through with all these dependent changes across the entire
// tree.
- public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
+ /**
+ * Register a new agent. {@see #registerNetworkAgent} below.
+ */
+ public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkAgentConfig networkAgentConfig) {
return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities,
@@ -5526,8 +5529,9 @@
* {@link NetworkAgentInfo#getCurrentScore}.
* @param networkAgentConfig metadata about the network. This is never updated.
* @param providerId the ID of the provider owning this NetworkAgent.
+ * @return the network created for this agent.
*/
- public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
+ public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) {
enforceNetworkFactoryPermission();
@@ -5560,7 +5564,7 @@
// If the network disconnects or sends any other event before that, messages are deferred by
// NetworkAgent until nai.asyncChannel.connect(), which will be called when finalizing the
// registration.
- return nai.network.netId;
+ return nai.network;
}
private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index b26ef92..d1d1cb3 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -523,7 +523,7 @@
@Override
public void accept(INetworkScoreCache networkScoreCache, Object cookie) {
- int filterType = NetworkScoreManager.CACHE_FILTER_NONE;
+ int filterType = NetworkScoreManager.SCORE_FILTER_NONE;
if (cookie instanceof Integer) {
filterType = (Integer) cookie;
}
@@ -547,17 +547,17 @@
private List<ScoredNetwork> filterScores(List<ScoredNetwork> scoredNetworkList,
int filterType) {
switch (filterType) {
- case NetworkScoreManager.CACHE_FILTER_NONE:
+ case NetworkScoreManager.SCORE_FILTER_NONE:
return scoredNetworkList;
- case NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK:
+ case NetworkScoreManager.SCORE_FILTER_CURRENT_NETWORK:
if (mCurrentNetworkFilter == null) {
mCurrentNetworkFilter =
new CurrentNetworkScoreCacheFilter(new WifiInfoSupplier(mContext));
}
return mCurrentNetworkFilter.apply(scoredNetworkList);
- case NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS:
+ case NetworkScoreManager.SCORE_FILTER_SCAN_RESULTS:
if (mScanResultsFilter == null) {
mScanResultsFilter = new ScanResultsScoreCacheFilter(
new ScanResultsSupplier(mContext));
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index c27b0da..ed3bab9 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -218,7 +218,7 @@
// Has to be in TestNetworkAgent to ensure all teardown codepaths properly clean up
// resources, even for binder death or unwanted calls.
synchronized (mTestNetworkTracker) {
- mTestNetworkTracker.remove(netId);
+ mTestNetworkTracker.remove(network.netId);
}
}
}
@@ -337,7 +337,7 @@
callingUid,
binder);
- mTestNetworkTracker.put(agent.netId, agent);
+ mTestNetworkTracker.put(agent.network.netId, agent);
}
} catch (SocketException e) {
throw new UncheckedIOException(e);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index a372fca0..debc2a1 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2129,16 +2129,6 @@
}
@Override
- public void removeAccount(IAccountManagerResponse response, Account account,
- boolean expectActivityLaunch) {
- removeAccountAsUser(
- response,
- account,
- expectActivityLaunch,
- UserHandle.getCallingUserId());
- }
-
- @Override
public void removeAccountAsUser(IAccountManagerResponse response, Account account,
boolean expectActivityLaunch, int userId) {
final int callingUid = Binder.getCallingUid();
@@ -4454,12 +4444,6 @@
@Override
@NonNull
- public Account[] getAccounts(String type, String opPackageName) {
- return getAccountsAsUser(type, UserHandle.getCallingUserId(), opPackageName);
- }
-
- @Override
- @NonNull
public Account[] getAccountsForPackage(String packageName, int uid, String opPackageName) {
int callingUid = Binder.getCallingUid();
if (!UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c21adb0..8f6d981 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -16408,6 +16408,22 @@
}
@Override
+ public boolean updateMccMncConfiguration(String mcc, String mnc) {
+ int mccInt, mncInt;
+ try {
+ mccInt = Integer.parseInt(mcc);
+ mncInt = Integer.parseInt(mnc);
+ } catch (NumberFormatException | StringIndexOutOfBoundsException ex) {
+ Slog.e(TAG, "Error parsing mcc: " + mcc + " mnc: " + mnc + ". ex=" + ex);
+ return false;
+ }
+ Configuration config = new Configuration();
+ config.mcc = mccInt;
+ config.mnc = mncInt == 0 ? Configuration.MNC_ZERO : mncInt;
+ return mActivityTaskManager.updateConfiguration(config);
+ }
+
+ @Override
public int getLaunchedFromUid(IBinder activityToken) {
return mActivityTaskManager.getLaunchedFromUid(activityToken);
}
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index f15d999..8d26176 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -367,6 +367,8 @@
CompatConfig config = new CompatConfig(androidBuildClassifier, context);
config.initConfigFromLib(Environment.buildPath(
Environment.getRootDirectory(), "etc", "compatconfig"));
+ config.initConfigFromLib(Environment.buildPath(
+ Environment.getRootDirectory(), "system_ext", "etc", "compatconfig"));
return config;
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 476f3f8..1d2a905 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -848,7 +848,7 @@
}
public int getNetId() {
- return mNetworkAgent != null ? mNetworkAgent.netId : NETID_UNSET;
+ return mNetworkAgent != null ? mNetworkAgent.network.netId : NETID_UNSET;
}
private LinkProperties makeLinkProperties() {
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index 0d315cd..408c1c9 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -23,18 +23,22 @@
import android.media.MediaRoute2ProviderInfo;
import android.media.RoutingSessionInfo;
+import com.android.internal.annotations.GuardedBy;
+
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Objects;
abstract class MediaRoute2Provider {
final ComponentName mComponentName;
final String mUniqueId;
+ final Object mLock = new Object();
Callback mCallback;
private volatile MediaRoute2ProviderInfo mProviderInfo;
- private volatile List<RoutingSessionInfo> mSessionInfos = Collections.emptyList();
+
+ @GuardedBy("mLock")
+ final List<RoutingSessionInfo> mSessionInfos = new ArrayList<>();
MediaRoute2Provider(@NonNull ComponentName componentName) {
mComponentName = Objects.requireNonNull(componentName, "Component name must not be null.");
@@ -69,11 +73,12 @@
@NonNull
public List<RoutingSessionInfo> getSessionInfos() {
- return mSessionInfos;
+ synchronized (mLock) {
+ return mSessionInfos;
+ }
}
- void setProviderState(MediaRoute2ProviderInfo providerInfo,
- List<RoutingSessionInfo> sessionInfos) {
+ void setProviderState(MediaRoute2ProviderInfo providerInfo) {
if (providerInfo == null) {
mProviderInfo = null;
} else {
@@ -81,14 +86,6 @@
.setUniqueId(mUniqueId)
.build();
}
- List<RoutingSessionInfo> sessionInfoWithProviderId = new ArrayList<RoutingSessionInfo>();
- for (RoutingSessionInfo sessionInfo : sessionInfos) {
- sessionInfoWithProviderId.add(
- new RoutingSessionInfo.Builder(sessionInfo)
- .setProviderId(mUniqueId)
- .build());
- }
- mSessionInfos = sessionInfoWithProviderId;
}
void notifyProviderState() {
@@ -97,9 +94,8 @@
}
}
- void setAndNotifyProviderState(MediaRoute2ProviderInfo providerInfo,
- List<RoutingSessionInfo> sessionInfos) {
- setProviderState(providerInfo, sessionInfos);
+ void setAndNotifyProviderState(MediaRoute2ProviderInfo providerInfo) {
+ setProviderState(providerInfo);
notifyProviderState();
}
@@ -112,10 +108,9 @@
void onProviderStateChanged(@Nullable MediaRoute2Provider provider);
void onSessionCreated(@NonNull MediaRoute2Provider provider,
@Nullable RoutingSessionInfo sessionInfo, long requestId);
- // TODO: Remove this when MediaRouter2ServiceImpl notifies clients of session changes.
- void onSessionInfoChanged(@NonNull MediaRoute2Provider provider,
+ void onSessionCreationFailed(@NonNull MediaRoute2Provider provider, long requestId);
+ void onSessionUpdated(@NonNull MediaRoute2Provider provider,
@NonNull RoutingSessionInfo sessionInfo);
- // TODO: Call this when service actually notifies of session release.
void onSessionReleased(@NonNull MediaRoute2Provider provider,
@NonNull RoutingSessionInfo sessionInfo);
}
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index c0ad46f..3840d02 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -17,7 +17,6 @@
package com.android.server.media;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -37,8 +36,6 @@
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
-import java.util.Collections;
-import java.util.List;
import java.util.Objects;
/**
@@ -270,35 +267,69 @@
}
private void onProviderStateUpdated(Connection connection,
- MediaRoute2ProviderInfo providerInfo, List<RoutingSessionInfo> sessionInfos) {
+ MediaRoute2ProviderInfo providerInfo) {
if (mActiveConnection != connection) {
return;
}
if (DEBUG) {
Slog.d(TAG, this + ": State changed ");
}
- setAndNotifyProviderState(providerInfo, sessionInfos);
+ setAndNotifyProviderState(providerInfo);
}
- private void onSessionCreated(Connection connection, @Nullable RoutingSessionInfo sessionInfo,
+ private void onSessionCreated(Connection connection, RoutingSessionInfo sessionInfo,
long requestId) {
if (mActiveConnection != connection) {
return;
}
- if (sessionInfo != null) {
- sessionInfo = new RoutingSessionInfo.Builder(sessionInfo)
- .setProviderId(getUniqueId())
- .build();
+
+ if (sessionInfo == null) {
+ Slog.w(TAG, "onSessionCreated: Ignoring null sessionInfo sent from " + mComponentName);
+ return;
}
+
+ sessionInfo = new RoutingSessionInfo.Builder(sessionInfo)
+ .setProviderId(getUniqueId())
+ .build();
+
+ boolean duplicateSessionAlreadyExists = false;
+ synchronized (mLock) {
+ for (int i = 0; i < mSessionInfos.size(); i++) {
+ if (mSessionInfos.get(i).getId().equals(sessionInfo.getId())) {
+ duplicateSessionAlreadyExists = true;
+ break;
+ }
+ }
+ mSessionInfos.add(sessionInfo);
+ }
+
+ if (duplicateSessionAlreadyExists) {
+ Slog.w(TAG, "onSessionCreated: Duplicate session already exists. Ignoring.");
+ return;
+ }
+
mCallback.onSessionCreated(this, sessionInfo, requestId);
}
- private void onSessionInfoChanged(Connection connection, RoutingSessionInfo sessionInfo) {
+ private void onSessionCreationFailed(Connection connection, long requestId) {
+ if (mActiveConnection != connection) {
+ return;
+ }
+
+ if (requestId == MediaRoute2ProviderService.REQUEST_ID_UNKNOWN) {
+ Slog.w(TAG, "onSessionCreationFailed: Ignoring requestId REQUEST_ID_UNKNOWN");
+ return;
+ }
+
+ mCallback.onSessionCreationFailed(this, requestId);
+ }
+
+ private void onSessionUpdated(Connection connection, RoutingSessionInfo sessionInfo) {
if (mActiveConnection != connection) {
return;
}
if (sessionInfo == null) {
- Slog.w(TAG, "onSessionInfoChanged: Ignoring null sessionInfo sent from "
+ Slog.w(TAG, "onSessionUpdated: Ignoring null sessionInfo sent from "
+ mComponentName);
return;
}
@@ -307,7 +338,55 @@
.setProviderId(getUniqueId())
.build();
- mCallback.onSessionInfoChanged(this, sessionInfo);
+ boolean found = false;
+ synchronized (mLock) {
+ for (int i = 0; i < mSessionInfos.size(); i++) {
+ if (mSessionInfos.get(i).getId().equals(sessionInfo.getId())) {
+ mSessionInfos.set(i, sessionInfo);
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ Slog.w(TAG, "onSessionUpdated: Matching session info not found");
+ return;
+ }
+
+ mCallback.onSessionUpdated(this, sessionInfo);
+ }
+
+ private void onSessionReleased(Connection connection, RoutingSessionInfo sessionInfo) {
+ if (mActiveConnection != connection) {
+ return;
+ }
+ if (sessionInfo == null) {
+ Slog.w(TAG, "onSessionReleased: Ignoring null sessionInfo sent from " + mComponentName);
+ return;
+ }
+
+ sessionInfo = new RoutingSessionInfo.Builder(sessionInfo)
+ .setProviderId(getUniqueId())
+ .build();
+
+ boolean found = false;
+ synchronized (mLock) {
+ for (int i = 0; i < mSessionInfos.size(); i++) {
+ if (mSessionInfos.get(i).getId().equals(sessionInfo.getId())) {
+ mSessionInfos.remove(i);
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ Slog.w(TAG, "onSessionReleased: Matching session info not found");
+ return;
+ }
+
+ mCallback.onSessionReleased(this, sessionInfo);
}
private void disconnect() {
@@ -315,7 +394,7 @@
mConnectionReady = false;
mActiveConnection.dispose();
mActiveConnection = null;
- setAndNotifyProviderState(null, Collections.emptyList());
+ setAndNotifyProviderState(null);
}
}
@@ -421,19 +500,24 @@
mHandler.post(() -> onConnectionDied(Connection.this));
}
- void postProviderStateUpdated(MediaRoute2ProviderInfo providerInfo,
- List<RoutingSessionInfo> sessionInfos) {
- mHandler.post(() -> onProviderStateUpdated(Connection.this,
- providerInfo, sessionInfos));
+ void postProviderStateUpdated(MediaRoute2ProviderInfo providerInfo) {
+ mHandler.post(() -> onProviderStateUpdated(Connection.this, providerInfo));
}
- void postSessionCreated(@Nullable RoutingSessionInfo sessionInfo, long requestId) {
- mHandler.post(() -> onSessionCreated(Connection.this, sessionInfo,
- requestId));
+ void postSessionCreated(RoutingSessionInfo sessionInfo, long requestId) {
+ mHandler.post(() -> onSessionCreated(Connection.this, sessionInfo, requestId));
}
- void postSessionInfoChanged(RoutingSessionInfo sessionInfo) {
- mHandler.post(() -> onSessionInfoChanged(Connection.this, sessionInfo));
+ void postSessionCreationFailed(long requestId) {
+ mHandler.post(() -> onSessionCreationFailed(Connection.this, requestId));
+ }
+
+ void postSessionUpdated(RoutingSessionInfo sessionInfo) {
+ mHandler.post(() -> onSessionUpdated(Connection.this, sessionInfo));
+ }
+
+ void postSessionReleased(RoutingSessionInfo sessionInfo) {
+ mHandler.post(() -> onSessionReleased(Connection.this, sessionInfo));
}
}
@@ -449,16 +533,15 @@
}
@Override
- public void updateState(MediaRoute2ProviderInfo providerInfo,
- List<RoutingSessionInfo> sessionInfos) {
+ public void updateState(MediaRoute2ProviderInfo providerInfo) {
Connection connection = mConnectionRef.get();
if (connection != null) {
- connection.postProviderStateUpdated(providerInfo, sessionInfos);
+ connection.postProviderStateUpdated(providerInfo);
}
}
@Override
- public void notifySessionCreated(@Nullable RoutingSessionInfo sessionInfo, long requestId) {
+ public void notifySessionCreated(RoutingSessionInfo sessionInfo, long requestId) {
Connection connection = mConnectionRef.get();
if (connection != null) {
connection.postSessionCreated(sessionInfo, requestId);
@@ -466,10 +549,26 @@
}
@Override
- public void notifySessionInfoChanged(RoutingSessionInfo sessionInfo) {
+ public void notifySessionCreationFailed(long requestId) {
Connection connection = mConnectionRef.get();
if (connection != null) {
- connection.postSessionInfoChanged(sessionInfo);
+ connection.postSessionCreationFailed(requestId);
+ }
+ }
+
+ @Override
+ public void notifySessionUpdated(RoutingSessionInfo sessionInfo) {
+ Connection connection = mConnectionRef.get();
+ if (connection != null) {
+ connection.postSessionUpdated(sessionInfo);
+ }
+ }
+
+ @Override
+ public void notifySessionReleased(RoutingSessionInfo sessionInfo) {
+ Connection connection = mConnectionRef.get();
+ if (connection != null) {
+ connection.postSessionReleased(sessionInfo);
}
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index c48c90d..d940e35 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -22,7 +22,6 @@
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
@@ -31,6 +30,7 @@
import android.media.IMediaRouter2Manager;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2ProviderInfo;
+import android.media.MediaRoute2ProviderService;
import android.media.RouteDiscoveryPreference;
import android.media.RoutingSessionInfo;
import android.os.Binder;
@@ -876,13 +876,19 @@
@Override
public void onSessionCreated(@NonNull MediaRoute2Provider provider,
- @Nullable RoutingSessionInfo sessionInfo, long requestId) {
+ @NonNull RoutingSessionInfo sessionInfo, long requestId) {
sendMessage(PooledLambda.obtainMessage(UserHandler::onSessionCreatedOnHandler,
this, provider, sessionInfo, requestId));
}
@Override
- public void onSessionInfoChanged(@NonNull MediaRoute2Provider provider,
+ public void onSessionCreationFailed(@NonNull MediaRoute2Provider provider, long requestId) {
+ sendMessage(PooledLambda.obtainMessage(UserHandler::onSessionCreationFailedOnHandler,
+ this, provider, requestId));
+ }
+
+ @Override
+ public void onSessionUpdated(@NonNull MediaRoute2Provider provider,
@NonNull RoutingSessionInfo sessionInfo) {
sendMessage(PooledLambda.obtainMessage(UserHandler::onSessionInfoChangedOnHandler,
this, provider, sessionInfo));
@@ -1132,7 +1138,14 @@
}
private void onSessionCreatedOnHandler(@NonNull MediaRoute2Provider provider,
- @Nullable RoutingSessionInfo sessionInfo, long requestId) {
+ @NonNull RoutingSessionInfo sessionInfo, long requestId) {
+
+ if (requestId == MediaRoute2ProviderService.REQUEST_ID_UNKNOWN) {
+ // The session is created without any matching request.
+ // TODO: Tell managers for the session creation
+ return;
+ }
+
SessionCreationRequest matchingRequest = null;
for (SessionCreationRequest request : mSessionCreationRequests) {
@@ -1182,6 +1195,30 @@
// TODO: Tell managers for the session creation
}
+ private void onSessionCreationFailedOnHandler(@NonNull MediaRoute2Provider provider,
+ long requestId) {
+ SessionCreationRequest matchingRequest = null;
+
+ for (SessionCreationRequest request : mSessionCreationRequests) {
+ if (request.mRequestId == requestId
+ && TextUtils.equals(
+ request.mRoute.getProviderId(), provider.getUniqueId())) {
+ matchingRequest = request;
+ break;
+ }
+ }
+
+ if (matchingRequest == null) {
+ Slog.w(TAG, "Ignoring session creation failed result for unknown request. "
+ + "requestId=" + requestId);
+ return;
+ }
+
+ mSessionCreationRequests.remove(matchingRequest);
+ notifySessionCreationFailed(matchingRequest.mClientRecord,
+ toClientRequestId(requestId));
+ }
+
private void onSessionInfoChangedOnHandler(@NonNull MediaRoute2Provider provider,
@NonNull RoutingSessionInfo sessionInfo) {
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 961d3d0..6695227 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -169,7 +169,7 @@
for (MediaRoute2Info route : mBluetoothRoutes) {
builder.addRoute(route);
}
- setProviderState(builder.build(), Collections.emptyList());
+ setProviderState(builder.build());
mHandler.post(() -> notifyProviderState());
}
@@ -212,6 +212,6 @@
for (MediaRoute2Info route : mBluetoothRoutes) {
builder.addRoute(route);
}
- setAndNotifyProviderState(builder.build(), Collections.emptyList());
+ setAndNotifyProviderState(builder.build());
}
}
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index ffcd6cf..bcfe577 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -338,9 +338,8 @@
}
@GuardedBy("mService.mLock")
- public void onPackageUninstalledLPw(@NonNull AndroidPackage pkg,
+ public void onPackageUninstalledLPw(@NonNull AndroidPackage pkg, @Nullable PackageSetting ps,
@NonNull int[] userIds) {
- PackageSetting ps = mService.getPackageSetting(pkg.getPackageName());
if (ps == null) {
return;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index dad32cd..159b4e4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -17502,7 +17502,8 @@
synchronized (mLock) {
if (res) {
if (pkg != null) {
- mInstantAppRegistry.onPackageUninstalledLPw(pkg, info.removedUsers);
+ mInstantAppRegistry.onPackageUninstalledLPw(pkg, uninstalledPs,
+ info.removedUsers);
}
updateSequenceNumberLP(uninstalledPs, info.removedUsers);
updateInstantAppInstallerLocked(packageName);
diff --git a/services/core/java/com/android/server/policy/LegacyGlobalActions.java b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
index 5271493..6daf516 100644
--- a/services/core/java/com/android/server/policy/LegacyGlobalActions.java
+++ b/services/core/java/com/android/server/policy/LegacyGlobalActions.java
@@ -743,8 +743,8 @@
} else if (TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) {
// Airplane mode can be changed after ECM exits if airplane toggle button
// is pressed during ECM mode
- if (!(intent.getBooleanExtra("PHONE_IN_ECM_STATE", false)) &&
- mIsWaitingForEcmExit) {
+ if (!(intent.getBooleanExtra(TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, false))
+ && mIsWaitingForEcmExit) {
mIsWaitingForEcmExit = false;
changeAirplaneModeSystemSetting(true);
}
diff --git a/services/core/java/com/android/server/stats/StatsPullAtomService.java b/services/core/java/com/android/server/stats/StatsPullAtomService.java
index bb910b2..5ee7eff 100644
--- a/services/core/java/com/android/server/stats/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/StatsPullAtomService.java
@@ -911,11 +911,26 @@
}
private void registerPowerProfile() {
- // No op.
+ int tagId = StatsLog.POWER_PROFILE;
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ /* PullAtomMetadata */ null,
+ (atomTag, data) -> pullPowerProfile(atomTag, data),
+ Executors.newSingleThreadExecutor()
+ );
}
- private void pullPowerProfile() {
- // No op.
+ private int pullPowerProfile(int atomTag, List<StatsEvent> pulledData) {
+ PowerProfile powerProfile = new PowerProfile(mContext);
+ ProtoOutputStream proto = new ProtoOutputStream();
+ powerProfile.dumpDebug(proto);
+ proto.flush();
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeByteArray(proto.getBytes())
+ .build();
+ pulledData.add(e);
+ return StatsManager.PULL_SUCCESS;
}
private void registerProcessCpuTime() {
diff --git a/services/core/java/com/android/server/utils/quota/QuotaTracker.java b/services/core/java/com/android/server/utils/quota/QuotaTracker.java
index ef1f426..a8cf9f6 100644
--- a/services/core/java/com/android/server/utils/quota/QuotaTracker.java
+++ b/services/core/java/com/android/server/utils/quota/QuotaTracker.java
@@ -172,6 +172,16 @@
// Exposed API to users.
+ /** Remove all saved events from the tracker. */
+ public void clear() {
+ synchronized (mLock) {
+ mInQuotaAlarmListener.clearLocked();
+ mFreeQuota.clear();
+
+ dropEverythingLocked();
+ }
+ }
+
/**
* @return true if the UPTC is within quota, false otherwise.
* @throws IllegalStateException if given categorizer returns a Category that's not recognized.
@@ -245,10 +255,7 @@
mIsEnabled = enable;
if (!mIsEnabled) {
- mInQuotaAlarmListener.clearLocked();
- mFreeQuota.clear();
-
- dropEverythingLocked();
+ clear();
}
}
}
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 4696dd0..0275f3e 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -33,7 +33,6 @@
#include "bpf/BpfUtils.h"
#include "netdbpf/BpfNetworkStats.h"
-using android::bpf::Stats;
using android::bpf::bpfGetUidStats;
using android::bpf::bpfGetIfaceStats;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6b81fdd..485899e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -23,7 +23,6 @@
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
import static android.app.admin.DevicePolicyManager.CODE_ACCOUNTS_NOT_EMPTY;
-import static android.app.admin.DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED;
import static android.app.admin.DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE;
import static android.app.admin.DevicePolicyManager.CODE_DEVICE_ADMIN_NOT_SUPPORTED;
import static android.app.admin.DevicePolicyManager.CODE_HAS_DEVICE_OWNER;
@@ -4118,6 +4117,12 @@
if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER, userHandle)) {
mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_USER, false, userHandle);
}
+ // When a device owner is set, the system automatically restricts adding a managed profile.
+ // Remove this restriction when the device owner is cleared.
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, userHandle)) {
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, false,
+ userHandle);
+ }
}
/**
@@ -8056,10 +8061,19 @@
updateDeviceOwnerLocked();
setDeviceOwnerSystemPropertyLocked();
- // TODO Send to system too?
- mInjector.binderWithCleanCallingIdentity(
- () -> sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED,
- userId));
+ mInjector.binderWithCleanCallingIdentity(() -> {
+ // Restrict adding a managed profile when a device owner is set on the device.
+ // That is to prevent the co-existence of a managed profile and a device owner
+ // on the same device.
+ // Instead, the device may be provisioned with an organization-owned managed
+ // profile, such that the admin on that managed profile has extended management
+ // capabilities that can affect the entire device (but not access private data
+ // on the primary profile).
+ mUserManager.setUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, true,
+ UserHandle.of(userId));
+ // TODO Send to system too?
+ sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED, userId);
+ });
mDeviceAdminServiceController.startServiceForOwner(
admin.getPackageName(), userId, "set-device-owner");
@@ -8322,6 +8336,17 @@
throw new IllegalArgumentException("Not active admin: " + who);
}
+ final int parentUserId = getProfileParentId(userHandle);
+ // When trying to set a profile owner on a new user, it may be that this user is
+ // a profile - but it may not be a managed profile if there's a restriction on the
+ // parent to add managed profiles (e.g. if the device has a device owner).
+ if (parentUserId != userHandle && mUserManager.hasUserRestriction(
+ UserManager.DISALLOW_ADD_MANAGED_PROFILE,
+ UserHandle.of(parentUserId))) {
+ Slog.i(LOG_TAG, "Cannot set profile owner because of restriction.");
+ return false;
+ }
+
if (isAdb()) {
// Log profile owner provisioning was started using adb.
MetricsLogger.action(mContext, PROVISIONING_ENTRY_POINT_ADB, LOG_TAG_PROFILE_OWNER);
@@ -12387,25 +12412,41 @@
final long ident = mInjector.binderClearCallingIdentity();
try {
final UserHandle callingUserHandle = UserHandle.of(callingUserId);
- final ComponentName ownerAdmin = getOwnerComponent(packageName, callingUserId);
- if (mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE,
- callingUserHandle)) {
- // An admin can initiate provisioning if it has set the restriction.
- if (ownerAdmin == null || isAdminAffectedByRestriction(ownerAdmin,
- UserManager.DISALLOW_ADD_MANAGED_PROFILE, callingUserId)) {
- return CODE_ADD_MANAGED_PROFILE_DISALLOWED;
- }
+ final boolean hasDeviceOwner;
+ synchronized (getLockObject()) {
+ hasDeviceOwner = getDeviceOwnerAdminLocked() != null;
}
- boolean canRemoveProfile = true;
- if (mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
- callingUserHandle)) {
- // We can remove a profile if the admin itself has set the restriction.
- if (ownerAdmin == null || isAdminAffectedByRestriction(ownerAdmin,
- UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
- callingUserId)) {
- canRemoveProfile = false;
- }
+
+ final boolean addingProfileRestricted = mUserManager.hasUserRestriction(
+ UserManager.DISALLOW_ADD_MANAGED_PROFILE, callingUserHandle);
+
+ UserInfo parentUser = mUserManager.getProfileParent(callingUserId);
+ final boolean addingProfileRestrictedOnParent = (parentUser != null)
+ && mUserManager.hasUserRestriction(
+ UserManager.DISALLOW_ADD_MANAGED_PROFILE,
+ UserHandle.of(parentUser.id));
+
+ Slog.i(LOG_TAG, String.format(
+ "When checking for managed profile provisioning: Has device owner? %b, adding"
+ + " profile restricted? %b, adding profile restricted on parent? %b",
+ hasDeviceOwner, addingProfileRestricted, addingProfileRestrictedOnParent));
+
+ // If there's a device owner, the restriction on adding a managed profile must be set
+ // somewhere.
+ if (hasDeviceOwner && !addingProfileRestricted && !addingProfileRestrictedOnParent) {
+ Slog.wtf(LOG_TAG, "Has a device owner but no restriction on adding a profile.");
}
+
+ // Do not allow adding a managed profile if there's a restriction, either on the current
+ // user or its parent user.
+ if (addingProfileRestricted || addingProfileRestrictedOnParent) {
+ return CODE_CANNOT_ADD_MANAGED_PROFILE;
+ }
+ // If there's a restriction on removing the managed profile then we have to take it
+ // into account when checking whether more profiles can be added.
+ boolean canRemoveProfile =
+ !mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
+ callingUserHandle);
if (!mUserManager.canAddMoreManagedProfiles(callingUserId, canRemoveProfile)) {
return CODE_CANNOT_ADD_MANAGED_PROFILE;
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 2fb2021..e609adc 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -16,7 +16,7 @@
package com.android.server;
-import static android.net.NetworkScoreManager.CACHE_FILTER_NONE;
+import static android.net.NetworkScoreManager.SCORE_FILTER_NONE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -306,7 +306,7 @@
bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
- mNetworkScoreCache, CACHE_FILTER_NONE);
+ mNetworkScoreCache, SCORE_FILTER_NONE);
mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
@@ -321,9 +321,9 @@
bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI,
- mNetworkScoreCache, CACHE_FILTER_NONE);
+ mNetworkScoreCache, SCORE_FILTER_NONE);
mNetworkScoreService.registerNetworkScoreCache(
- NetworkKey.TYPE_WIFI, mNetworkScoreCache2, CACHE_FILTER_NONE);
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache2, SCORE_FILTER_NONE);
// updateScores should update both caches
mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK});
@@ -378,7 +378,7 @@
bindToScorer(true /*callerIsScorer*/);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
- CACHE_FILTER_NONE);
+ SCORE_FILTER_NONE);
mNetworkScoreService.clearScores();
verify(mNetworkScoreCache).clearScores();
@@ -392,7 +392,7 @@
.thenReturn(PackageManager.PERMISSION_GRANTED);
mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache,
- CACHE_FILTER_NONE);
+ SCORE_FILTER_NONE);
mNetworkScoreService.clearScores();
verify(mNetworkScoreCache).clearScores();
@@ -472,7 +472,7 @@
try {
mNetworkScoreService.registerNetworkScoreCache(
- NetworkKey.TYPE_WIFI, mNetworkScoreCache, CACHE_FILTER_NONE);
+ NetworkKey.TYPE_WIFI, mNetworkScoreCache, SCORE_FILTER_NONE);
fail("SecurityException expected");
} catch (SecurityException e) {
// expected
@@ -615,7 +615,7 @@
new ArrayList<>(scoredNetworkList),
NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
- consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);
+ consumer.accept(mNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_NONE);
verify(mNetworkScoreCache).updateScores(scoredNetworkList);
verifyZeroInteractions(mCurrentNetworkFilter, mScanResultsFilter);
@@ -656,7 +656,7 @@
Collections.emptyList(),
NetworkKey.TYPE_WIFI, mCurrentNetworkFilter, mScanResultsFilter);
- consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_NONE);
+ consumer.accept(mNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_NONE);
verifyZeroInteractions(mNetworkScoreCache, mCurrentNetworkFilter, mScanResultsFilter);
}
@@ -673,7 +673,7 @@
List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
filteredList.remove(SCORED_NETWORK);
when(mCurrentNetworkFilter.apply(scoredNetworkList)).thenReturn(filteredList);
- consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_CURRENT_NETWORK);
+ consumer.accept(mNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_CURRENT_NETWORK);
verify(mNetworkScoreCache).updateScores(filteredList);
verifyZeroInteractions(mScanResultsFilter);
@@ -691,7 +691,7 @@
List<ScoredNetwork> filteredList = new ArrayList<>(scoredNetworkList);
filteredList.remove(SCORED_NETWORK);
when(mScanResultsFilter.apply(scoredNetworkList)).thenReturn(filteredList);
- consumer.accept(mNetworkScoreCache, NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS);
+ consumer.accept(mNetworkScoreCache, NetworkScoreManager.SCORE_FILTER_SCAN_RESULTS);
verify(mNetworkScoreCache).updateScores(filteredList);
verifyZeroInteractions(mCurrentNetworkFilter);
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 0f11566..39a3aae 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -212,7 +212,8 @@
String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
- Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
+ Account[] accounts = mAms.getAccountsAsUser(null,
+ UserHandle.getCallingUserId(), mContext.getOpPackageName());
Arrays.sort(accounts, new AccountSorter());
assertEquals(6, accounts.length);
assertEquals(a11, accounts[0]);
@@ -222,8 +223,8 @@
assertEquals(a22, accounts[4]);
assertEquals(a32, accounts[5]);
- accounts = mAms.getAccounts(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
- mContext.getOpPackageName());
+ accounts = mAms.getAccountsAsUser(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ UserHandle.getCallingUserId(), mContext.getOpPackageName());
Arrays.sort(accounts, new AccountSorter());
assertEquals(3, accounts.length);
assertEquals(a11, accounts[0]);
@@ -232,8 +233,8 @@
mAms.removeAccountInternal(a21);
- accounts = mAms.getAccounts(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
- mContext.getOpPackageName());
+ accounts = mAms.getAccountsAsUser(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+ UserHandle.getCallingUserId(), mContext.getOpPackageName());
Arrays.sort(accounts, new AccountSorter());
assertEquals(2, accounts.length);
assertEquals(a11, accounts[0]);
@@ -373,7 +374,8 @@
unlockSystemUser();
String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
- Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
+ Account[] accounts = mAms.getAccountsAsUser(null, UserHandle.getCallingUserId(),
+ mContext.getOpPackageName());
assertEquals("1 account should be migrated", 1, accounts.length);
assertEquals(PreNTestDatabaseHelper.ACCOUNT_NAME, accounts[0].name);
assertEquals(PreNTestDatabaseHelper.ACCOUNT_PASSWORD, mAms.getPassword(accounts[0]));
@@ -2980,7 +2982,8 @@
Log.d(TAG, logPrefix + " getAccounts started");
long ti = System.currentTimeMillis();
try {
- Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
+ Account[] accounts = mAms.getAccountsAsUser(null,
+ UserHandle.getCallingUserId(), mContext.getOpPackageName());
if (accounts == null || accounts.length != 1
|| !AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1.equals(
accounts[0].type)) {
@@ -3051,7 +3054,8 @@
Log.d(TAG, logPrefix + " getAccounts started");
long ti = System.currentTimeMillis();
try {
- Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
+ Account[] accounts = mAms.getAccountsAsUser(null,
+ UserHandle.getCallingUserId(), mContext.getOpPackageName());
if (accounts == null || accounts.length != 1
|| !AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1.equals(
accounts[0].type)) {
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 21034d3..45729e5 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -34,6 +34,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
@@ -275,6 +276,29 @@
}).when(getServices().userManager).getApplicationRestrictions(
anyString(), any(UserHandle.class));
+ // Emulate UserManager.setUserRestriction/getUserRestrictions
+ final Map<UserHandle, Bundle> userRestrictions = new HashMap<>();
+
+ doAnswer((Answer<Void>) invocation -> {
+ String key = (String) invocation.getArguments()[0];
+ boolean value = (Boolean) invocation.getArguments()[1];
+ UserHandle user = (UserHandle) invocation.getArguments()[2];
+ Bundle userBundle = userRestrictions.getOrDefault(user, new Bundle());
+ userBundle.putBoolean(key, value);
+
+ userRestrictions.put(user, userBundle);
+ return null;
+ }).when(getServices().userManager).setUserRestriction(
+ anyString(), anyBoolean(), any(UserHandle.class));
+
+ doAnswer((Answer<Boolean>) invocation -> {
+ String key = (String) invocation.getArguments()[0];
+ UserHandle user = (UserHandle) invocation.getArguments()[1];
+ Bundle userBundle = userRestrictions.getOrDefault(user, new Bundle());
+ return userBundle.getBoolean(key);
+ }).when(getServices().userManager).hasUserRestriction(
+ anyString(), any(UserHandle.class));
+
// Add the first secondary user.
getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
UserManager.USER_TYPE_FULL_SECONDARY);
@@ -822,10 +846,8 @@
final int MANAGED_PROFILE_ADMIN_UID =
UserHandle.getUid(MANAGED_PROFILE_USER_ID, DpmMockContext.SYSTEM_UID);
- // Setup device owner.
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
mContext.packageName = admin1.getPackageName();
- setupDeviceOwner();
// Add a managed profile belonging to the system user.
addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
@@ -833,18 +855,13 @@
// Change the parent user's password.
dpm.reportPasswordChanged(UserHandle.USER_SYSTEM);
- // Both the device owner and the managed profile owner should receive this broadcast.
+ // The managed profile owner should receive this broadcast.
final Intent intent = new Intent(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED);
intent.setComponent(admin1);
intent.putExtra(Intent.EXTRA_USER, UserHandle.of(UserHandle.USER_SYSTEM));
verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
MockUtils.checkIntent(intent),
- MockUtils.checkUserHandle(UserHandle.USER_SYSTEM),
- eq(null),
- any(Bundle.class));
- verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
- MockUtils.checkIntent(intent),
MockUtils.checkUserHandle(MANAGED_PROFILE_USER_ID),
eq(null),
any(Bundle.class));
@@ -864,12 +881,11 @@
final int MANAGED_PROFILE_ADMIN_UID =
UserHandle.getUid(MANAGED_PROFILE_USER_ID, DpmMockContext.SYSTEM_UID);
- // Setup device owner.
+ // Configure system as having separate profile challenge.
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
mContext.packageName = admin1.getPackageName();
doReturn(true).when(getServices().lockPatternUtils)
.isSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID);
- setupDeviceOwner();
// Add a managed profile belonging to the system user.
addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
@@ -954,6 +970,10 @@
verify(getServices().iactivityManager, times(1)).updateDeviceOwner(
eq(admin1.getPackageName()));
+ verify(getServices().userManager, times(1)).setUserRestriction(
+ eq(UserManager.DISALLOW_ADD_MANAGED_PROFILE),
+ eq(true), eq(UserHandle.SYSTEM));
+
verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
MockUtils.checkIntentAction(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED),
MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
@@ -2005,12 +2025,11 @@
assertNoDeviceOwnerRestrictions();
- // Initialize DPMS again and check that the user restriction wasn't enabled again.
reset(getServices().userManagerInternal);
- initializeDpms();
- assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertNotNull(dpms.getDeviceOwnerAdminLocked());
+ // Ensure the DISALLOW_REMOVE_MANAGED_PROFILES restriction doesn't show up as a
+ // restriction to the device owner.
+ dpm.addUserRestriction(admin1, UserManager.DISALLOW_REMOVE_MANAGED_PROFILE);
assertNoDeviceOwnerRestrictions();
}
@@ -3106,7 +3125,6 @@
setup_nonSplitUser_withDo_primaryUser();
final int MANAGED_PROFILE_USER_ID = 18;
final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 1308);
- addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
false /* we can't remove a managed profile */)).thenReturn(false);
when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM,
@@ -3158,41 +3176,16 @@
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, false);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_FINANCED_DEVICE, false);
- // COMP mode is allowed.
+ // COMP mode NOT is allowed.
assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DevicePolicyManager.CODE_OK);
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
- // And other DPCs can also provision a managed profile (DO + BYOD case).
+ // And other DPCs can NOT provision a managed profile.
assertCheckProvisioningPreCondition(
DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
DpmMockContext.ANOTHER_PACKAGE_NAME,
- DevicePolicyManager.CODE_OK);
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true,
- DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
- }
-
- public void testProvisioning_nonSplitUser_withDo_primaryUser_restrictedByDo() throws Exception {
- setup_nonSplitUser_withDo_primaryUser();
- mContext.packageName = admin1.getPackageName();
- mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
- // The DO should be allowed to initiate provisioning if it set the restriction itself, but
- // other packages should be forbidden.
- when(getServices().userManager.hasUserRestriction(
- eq(UserManager.DISALLOW_ADD_MANAGED_PROFILE),
- eq(UserHandle.getUserHandleForUid(mContext.binder.callingUid))))
- .thenReturn(true);
- when(getServices().userManager.getUserRestrictionSource(
- eq(UserManager.DISALLOW_ADD_MANAGED_PROFILE),
- eq(UserHandle.getUserHandleForUid(mContext.binder.callingUid))))
- .thenReturn(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER);
- assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DevicePolicyManager.CODE_OK);
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
- assertCheckProvisioningPreCondition(
- DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DpmMockContext.ANOTHER_PACKAGE_NAME,
- DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false,
DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
}
@@ -3213,31 +3206,46 @@
eq(UserHandle.getUserHandleForUid(mContext.binder.callingUid))))
.thenReturn(UserManager.RESTRICTION_SOURCE_SYSTEM);
assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
assertCheckProvisioningPreCondition(
DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
DpmMockContext.ANOTHER_PACKAGE_NAME,
- DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false,
DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
}
- public void testCheckProvisioningPreCondition_nonSplitUser_comp() throws Exception {
+ public void testCheckCannotSetProfileOwnerWithDeviceOwner() throws Exception {
+ setup_nonSplitUser_withDo_primaryUser();
+ final int managedProfileUserId = 18;
+ final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 1308);
+
+ final int userId = UserHandle.getUserId(managedProfileAdminUid);
+ getServices().addUser(userId, 0, UserManager.USER_TYPE_PROFILE_MANAGED,
+ UserHandle.USER_SYSTEM);
+ mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS);
+ setUpPackageManagerForFakeAdmin(admin1, managedProfileAdminUid, admin1);
+ dpm.setActiveAdmin(admin1, false, userId);
+ assertFalse(dpm.setProfileOwner(admin1, null, userId));
+ mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
+ }
+
+ public void testCheckProvisioningPreCondition_nonSplitUser_attemptingComp() throws Exception {
setup_nonSplitUser_withDo_primaryUser_ManagedProfile();
mContext.packageName = admin1.getPackageName();
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
// We can delete the managed profile to create a new one, so provisioning is allowed.
assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DevicePolicyManager.CODE_OK);
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
assertCheckProvisioningPreCondition(
DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
DpmMockContext.ANOTHER_PACKAGE_NAME,
- DevicePolicyManager.CODE_OK);
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true,
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false,
DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
}
@@ -3265,8 +3273,8 @@
// But the device owner can still do it because it has set the restriction itself.
assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DevicePolicyManager.CODE_OK);
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
}
private void setup_splitUser_firstBoot_systemUser() throws Exception {
@@ -3475,6 +3483,8 @@
when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
.thenReturn(true);
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
+ when(getServices().userManager.getProfileParent(DpmMockContext.CALLER_USER_HANDLE))
+ .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "user system", 0));
when(getServices().userManager.canAddMoreManagedProfiles(DpmMockContext.CALLER_USER_HANDLE,
true)).thenReturn(true);
setUserSetupCompleteForUser(false, DpmMockContext.CALLER_USER_HANDLE);
@@ -3487,7 +3497,7 @@
setup_provisionManagedProfileWithDeviceOwner_primaryUser();
setUpPackageManagerForAdmin(admin1, mContext.binder.callingUid);
mContext.packageName = admin1.getPackageName();
- assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, true);
+ assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
}
public void testCheckProvisioningPreCondition_provisionManagedProfileWithDeviceOwner_primaryUser()
@@ -3495,9 +3505,9 @@
setup_provisionManagedProfileWithDeviceOwner_primaryUser();
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
- // COMP mode is allowed.
+ // COMP mode is NOT allowed.
assertCheckProvisioningPreCondition(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE,
- DevicePolicyManager.CODE_OK);
+ DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
}
private void setup_provisionManagedProfileCantRemoveUser_primaryUser() throws Exception {
@@ -4014,11 +4024,6 @@
List<UserHandle> targetUsers = dpm.getBindDeviceAdminTargetUsers(admin1);
MoreAsserts.assertEmpty(targetUsers);
- // Setup a managed profile managed by the same admin.
- final int MANAGED_PROFILE_USER_ID = 15;
- final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 20456);
- addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
-
// Add a secondary user, it should never talk with.
final int ANOTHER_USER_ID = 36;
getServices().addUser(ANOTHER_USER_ID, 0, UserManager.USER_TYPE_FULL_SECONDARY);
@@ -4028,30 +4033,11 @@
targetUsers = dpm.getBindDeviceAdminTargetUsers(admin1);
MoreAsserts.assertEmpty(targetUsers);
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- targetUsers = dpm.getBindDeviceAdminTargetUsers(admin1);
- MoreAsserts.assertEmpty(targetUsers);
-
// Setting affiliation ids
final Set<String> userAffiliationIds = Collections.singleton("some.affiliation-id");
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
dpm.setAffiliationIds(admin1, userAffiliationIds);
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- dpm.setAffiliationIds(admin1, userAffiliationIds);
-
- // Calling from device owner admin, the result list should just contain the managed
- // profile user id.
- mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- targetUsers = dpm.getBindDeviceAdminTargetUsers(admin1);
- MoreAsserts.assertContentsInAnyOrder(targetUsers, UserHandle.of(MANAGED_PROFILE_USER_ID));
-
- // Calling from managed profile admin, the result list should just contain the system
- // user id.
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- targetUsers = dpm.getBindDeviceAdminTargetUsers(admin1);
- MoreAsserts.assertContentsInAnyOrder(targetUsers, UserHandle.SYSTEM);
-
// Changing affiliation ids in one
dpm.setAffiliationIds(admin1, Collections.singleton("some-different-affiliation-id"));
@@ -4065,38 +4051,6 @@
MoreAsserts.assertEmpty(targetUsers);
}
- public void testGetBindDeviceAdminTargetUsers_differentPackage() throws Exception {
- // Setup a device owner.
- mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- setupDeviceOwner();
-
- // Set up a managed profile managed by different package.
- final int MANAGED_PROFILE_USER_ID = 15;
- final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 20456);
- final ComponentName adminDifferentPackage =
- new ComponentName("another.package", "whatever.class");
- addManagedProfile(adminDifferentPackage, MANAGED_PROFILE_ADMIN_UID, admin2);
-
- // Setting affiliation ids
- final Set<String> userAffiliationIds = Collections.singleton("some-affiliation-id");
- dpm.setAffiliationIds(admin1, userAffiliationIds);
-
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- dpm.setAffiliationIds(adminDifferentPackage, userAffiliationIds);
-
- // Calling from device owner admin, we should get zero bind device admin target users as
- // their packages are different.
- mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- List<UserHandle> targetUsers = dpm.getBindDeviceAdminTargetUsers(admin1);
- MoreAsserts.assertEmpty(targetUsers);
-
- // Calling from managed profile admin, we should still get zero target users for the same
- // reason.
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- targetUsers = dpm.getBindDeviceAdminTargetUsers(adminDifferentPackage);
- MoreAsserts.assertEmpty(targetUsers);
- }
-
private void verifyLockTaskState(int userId) throws Exception {
verifyLockTaskState(userId, new String[0],
DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS);
@@ -4133,79 +4087,6 @@
() -> dpm.setLockTaskFeatures(who, flags));
}
- public void testLockTaskPolicyAllowedForAffiliatedUsers() throws Exception {
- // Setup a device owner.
- mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- setupDeviceOwner();
- // Lock task policy is updated when loading user data.
- verifyLockTaskState(UserHandle.USER_SYSTEM);
-
- // Set up a managed profile managed by different package (package name shouldn't matter)
- final int MANAGED_PROFILE_USER_ID = 15;
- final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 20456);
- final ComponentName adminDifferentPackage =
- new ComponentName("another.package", "whatever.class");
- addManagedProfile(adminDifferentPackage, MANAGED_PROFILE_ADMIN_UID, admin2);
- verifyLockTaskState(MANAGED_PROFILE_USER_ID);
-
- // Setup a PO on the secondary user
- mContext.binder.callingUid = DpmMockContext.CALLER_UID;
- setAsProfileOwner(admin3);
- verifyLockTaskState(DpmMockContext.CALLER_USER_HANDLE);
-
- // The DO can still set lock task packages
- final String[] doPackages = {"doPackage1", "doPackage2"};
- final int flags = DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS
- | DevicePolicyManager.LOCK_TASK_FEATURE_HOME
- | DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
- verifyCanSetLockTask(DpmMockContext.CALLER_SYSTEM_USER_UID, UserHandle.USER_SYSTEM, admin1, doPackages, flags);
-
- final String[] secondaryPoPackages = {"secondaryPoPackage1", "secondaryPoPackage2"};
- final int secondaryPoFlags = DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS
- | DevicePolicyManager.LOCK_TASK_FEATURE_HOME
- | DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
- verifyCanNotSetLockTask(DpmMockContext.CALLER_UID, admin3, secondaryPoPackages, secondaryPoFlags);
-
- // Managed profile is unaffiliated - shouldn't be able to setLockTaskPackages.
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- final String[] poPackages = {"poPackage1", "poPackage2"};
- final int poFlags = DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS
- | DevicePolicyManager.LOCK_TASK_FEATURE_HOME
- | DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
- verifyCanNotSetLockTask(MANAGED_PROFILE_ADMIN_UID, adminDifferentPackage, poPackages, poFlags);
-
- // Setting same affiliation ids
- final Set<String> userAffiliationIds = Collections.singleton("some-affiliation-id");
- mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- dpm.setAffiliationIds(admin1, userAffiliationIds);
-
- mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- dpm.setAffiliationIds(adminDifferentPackage, userAffiliationIds);
-
- // Now the managed profile can set lock task packages.
- dpm.setLockTaskPackages(adminDifferentPackage, poPackages);
- MoreAsserts.assertEquals(poPackages, dpm.getLockTaskPackages(adminDifferentPackage));
- assertTrue(dpm.isLockTaskPermitted("poPackage1"));
- assertFalse(dpm.isLockTaskPermitted("doPackage2"));
- // And it can set lock task features.
- dpm.setLockTaskFeatures(adminDifferentPackage, poFlags);
- verifyLockTaskState(MANAGED_PROFILE_USER_ID, poPackages, poFlags);
-
- // Unaffiliate the profile, lock task mode no longer available on the profile.
- dpm.setAffiliationIds(adminDifferentPackage, Collections.emptySet());
- assertFalse(dpm.isLockTaskPermitted("poPackage1"));
- // Lock task packages cleared when loading user data and when the user becomes unaffiliated.
- verify(getServices().iactivityManager, times(2)).updateLockTaskPackages(
- MANAGED_PROFILE_USER_ID, new String[0]);
- verify(getServices().iactivityTaskManager, times(2)).updateLockTaskFeatures(
- MANAGED_PROFILE_USER_ID, DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
-
- // Verify that lock task packages were not cleared for the DO
- mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- assertTrue(dpm.isLockTaskPermitted("doPackage1"));
-
- }
-
public void testLockTaskPolicyForProfileOwner() throws Exception {
// Setup a PO
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 1dd7e64..6aca58f 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -23,7 +23,8 @@
import static android.app.usage.UsageEvents.Event.SYSTEM_INTERACTION;
import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
import static android.app.usage.UsageStatsManager.REASON_MAIN_DEFAULT;
-import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED;
+import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_SYSTEM;
+import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_USER;
import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED;
import static android.app.usage.UsageStatsManager.REASON_MAIN_TIMEOUT;
import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
@@ -501,12 +502,18 @@
// Can force to NEVER
mInjector.mElapsedRealtime = HOUR_MS;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
- REASON_MAIN_FORCED);
+ REASON_MAIN_FORCED_BY_USER);
assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1));
- // Prediction can't override FORCED reason
+ // Prediction can't override FORCED reasons
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
+ REASON_MAIN_FORCED_BY_SYSTEM);
+ mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
+ REASON_MAIN_PREDICTED);
+ assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
+
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
- REASON_MAIN_FORCED);
+ REASON_MAIN_FORCED_BY_USER);
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
REASON_MAIN_PREDICTED);
assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1));
@@ -631,7 +638,7 @@
mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100;
// Make sure app is in NEVER bucket
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
- REASON_MAIN_FORCED);
+ REASON_MAIN_FORCED_BY_USER);
mController.checkIdleStates(USER_ID);
assertBucket(STANDBY_BUCKET_NEVER);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 8617833..5a7c3b3 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -16,8 +16,6 @@
package android.telephony;
-import com.android.telephony.Rlog;
-
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -36,6 +34,7 @@
import android.telephony.ims.ImsReasonInfo;
import com.android.internal.telephony.ICarrierConfigLoader;
+import com.android.telephony.Rlog;
/**
* Provides access to telephony configuration values that are carrier-specific.
@@ -300,7 +299,6 @@
/**
* A string array containing numbers that shouldn't be included in the call log.
- * @hide
*/
public static final String KEY_UNLOGGABLE_NUMBERS_STRING_ARRAY =
"unloggable_numbers_string_array";
@@ -313,12 +311,11 @@
KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL = "hide_carrier_network_settings_bool";
/**
- * Do only allow auto selection in Advanced Network Settings when in home network.
+ * Only allow auto selection in Advanced Network Settings when in home network.
* Manual selection is allowed when in roaming network.
- * @hide
*/
- public static final String
- KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL = "only_auto_select_in_home_network";
+ public static final String KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL =
+ "only_auto_select_in_home_network";
/**
* Control whether users receive a simplified network settings UI and improved network
@@ -582,9 +579,6 @@
* registration state to change. That is, turning on or off mobile data will not cause VT to be
* enabled or disabled.
* When {@code false}, disabling mobile data will cause VT to be de-registered.
- * <p>
- * See also {@link #KEY_VILTE_DATA_IS_METERED_BOOL}.
- * @hide
*/
public static final String KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS =
"ignore_data_enabled_changed_for_video_calls";
@@ -648,7 +642,6 @@
/**
* Default WFC_IMS_enabled: true VoWiFi by default is on
* false VoWiFi by default is off
- * @hide
*/
public static final String KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL =
"carrier_default_wfc_ims_enabled_bool";
@@ -720,9 +713,7 @@
*
* As of now, Verizon is the only carrier enforcing this dependency in their
* WFC awareness and activation requirements.
- *
- * @hide
- * */
+ */
public static final String KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL
= "carrier_volte_override_wfc_provisioning_bool";
@@ -1083,7 +1074,6 @@
*
* When {@code false}, the old behavior is used, where the toggle in accessibility settings is
* used to set the IMS stack's RTT enabled state.
- * @hide
*/
public static final String KEY_IGNORE_RTT_MODE_SETTING_BOOL =
"ignore_rtt_mode_setting_bool";
@@ -1124,7 +1114,6 @@
* Determines whether the IMS conference merge process supports and returns its participants
* data. When {@code true}, on merge complete, conference call would have a list of its
* participants returned in XML format, {@code false otherwise}.
- * @hide
*/
public static final String KEY_SUPPORT_IMS_CONFERENCE_EVENT_PACKAGE_BOOL =
"support_ims_conference_event_package_bool";
@@ -1197,20 +1186,18 @@
public static final String KEY_ENABLE_APPS_STRING_ARRAY = "enable_apps_string_array";
/**
- * Determine whether user can switch Wi-Fi preferred or Cellular preferred in calling preference.
+ * Determine whether user can switch Wi-Fi preferred or Cellular preferred
+ * in calling preference.
* Some operators support Wi-Fi Calling only, not VoLTE.
* They don't need "Cellular preferred" option.
- * In this case, set uneditalbe attribute for preferred preference.
- * @hide
+ * In this case, set uneditable attribute for preferred preference.
*/
public static final String KEY_EDITABLE_WFC_MODE_BOOL = "editable_wfc_mode_bool";
- /**
- * Flag to indicate if Wi-Fi needs to be disabled in ECBM
- * @hide
- **/
- public static final String
- KEY_CONFIG_WIFI_DISABLE_IN_ECBM = "config_wifi_disable_in_ecbm";
+ /**
+ * Flag to indicate if Wi-Fi needs to be disabled in ECBM.
+ */
+ public static final String KEY_CONFIG_WIFI_DISABLE_IN_ECBM = "config_wifi_disable_in_ecbm";
/**
* List operator-specific error codes and indices of corresponding error strings in
@@ -1274,9 +1261,8 @@
public static final String KEY_WFC_SPN_USE_ROOT_LOCALE = "wfc_spn_use_root_locale";
/**
- * The Component Name of the activity that can setup the emergency addrees for WiFi Calling
+ * The Component Name of the activity that can setup the emergency address for WiFi Calling
* as per carrier requirement.
- * @hide
*/
public static final String KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING =
"wfc_emergency_address_carrier_app_string";
@@ -1440,22 +1426,19 @@
public static final String KEY_ALLOW_ADDING_APNS_BOOL = "allow_adding_apns_bool";
/**
- * APN types that user is not allowed to modify
- * @hide
+ * APN types that user is not allowed to modify.
*/
public static final String KEY_READ_ONLY_APN_TYPES_STRING_ARRAY =
"read_only_apn_types_string_array";
/**
- * APN fields that user is not allowed to modify
- * @hide
+ * APN fields that user is not allowed to modify.
*/
public static final String KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY =
"read_only_apn_fields_string_array";
/**
* Default value of APN types field if not specified by user when adding/modifying an APN.
- * @hide
*/
public static final String KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY =
"apn_settings_default_apn_types_string_array";
@@ -1486,29 +1469,25 @@
"hide_digits_helper_text_on_stk_input_screen_bool";
/**
- * Boolean indicating if show data RAT icon on status bar even when data is disabled
- * @hide
+ * Boolean indicating if show data RAT icon on status bar even when data is disabled.
*/
public static final String KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL =
"always_show_data_rat_icon_bool";
/**
- * Boolean indicating if default data account should show LTE or 4G icon
- * @hide
+ * Boolean indicating if default data account should show LTE or 4G icon.
*/
public static final String KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL =
"show_4g_for_lte_data_icon_bool";
/**
* Boolean indicating if default data account should show 4G icon when in 3G.
- * @hide
*/
public static final String KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL =
"show_4g_for_3g_data_icon_bool";
/**
- * Boolean indicating if lte+ icon should be shown if available
- * @hide
+ * Boolean indicating if LTE+ icon should be shown if available.
*/
public static final String KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL =
"hide_lte_plus_data_icon_bool";
@@ -1523,10 +1502,8 @@
"operator_name_filter_pattern_string";
/**
- * The string is used to compare with operator name. If it matches the pattern then show
- * specific data icon.
- *
- * @hide
+ * The string is used to compare with operator name.
+ * If it matches the pattern then show specific data icon.
*/
public static final String KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING =
"show_carrier_data_icon_pattern_string";
@@ -1539,33 +1516,28 @@
"show_precise_failed_cause_bool";
/**
- * Boolean to decide whether lte is enabled.
- * @hide
+ * Boolean to decide whether LTE is enabled.
*/
public static final String KEY_LTE_ENABLED_BOOL = "lte_enabled_bool";
/**
* Boolean to decide whether TD-SCDMA is supported.
- * @hide
*/
public static final String KEY_SUPPORT_TDSCDMA_BOOL = "support_tdscdma_bool";
/**
* A list of mcc/mnc that support TD-SCDMA for device when connect to the roaming network.
- * @hide
*/
public static final String KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY =
"support_tdscdma_roaming_networks_string_array";
/**
* Boolean to decide whether world mode is enabled.
- * @hide
*/
public static final String KEY_WORLD_MODE_ENABLED_BOOL = "world_mode_enabled_bool";
/**
* Flatten {@link android.content.ComponentName} of the carrier's settings activity.
- * @hide
*/
public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING =
"carrier_settings_activity_component_name_string";
@@ -1619,25 +1591,23 @@
/**
* Defines carrier-specific actions which act upon
* com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED, used for customization of the
- * default carrier app
+ * default carrier app.
* Format: "CARRIER_ACTION_IDX, ..."
* Where {@code CARRIER_ACTION_IDX} is an integer defined in
- * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
+ * com.android.carrierdefaultapp.CarrierActionUtils
* Example:
- * {@link com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_DISABLE_METERED_APNS
- * disable_metered_apns}
- * @hide
+ * com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_DISABLE_METERED_APNS
+ * disables metered APNs
*/
- @UnsupportedAppUsage
+ @SuppressLint("IntentName")
public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY =
"carrier_default_actions_on_redirection_string_array";
/**
- * Defines carrier-specific actions which act upon
- * com.android.internal.telephony.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED
+ * Defines carrier-specific actions which act upon CARRIER_SIGNAL_REQUEST_NETWORK_FAILED
* and configured signal args:
- * {@link TelephonyManager#EXTRA_APN_TYPE apnType},
- * {@link TelephonyManager#EXTRA_ERROR_CODE errorCode}
+ * android.telephony.TelephonyManager#EXTRA_APN_TYPE,
+ * android.telephony.TelephonyManager#EXTRA_ERROR_CODE
* used for customization of the default carrier app
* Format:
* {
@@ -1645,42 +1615,41 @@
* "APN_1, ERROR_CODE_2 : CARRIER_ACTION_IDX_1 "
* }
* Where {@code APN_1} is a string defined in
- * {@link com.android.internal.telephony.PhoneConstants PhoneConstants}
+ * com.android.internal.telephony.PhoneConstants
* Example: "default"
*
- * {@code ERROR_CODE_1} is an integer defined in
- * {@link DataFailCause DcFailure}
+ * {@code ERROR_CODE_1} is an integer defined in android.telephony.DataFailCause
* Example:
- * {@link DataFailCause#MISSING_UNKNOWN_APN}
+ * android.telephony.DataFailCause#MISSING_UNKNOWN_APN
*
* {@code CARRIER_ACTION_IDX_1} is an integer defined in
- * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
+ * com.android.carrierdefaultapp.CarrierActionUtils
* Example:
- * {@link com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_DISABLE_METERED_APNS}
- * @hide
+ * com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_DISABLE_METERED_APNS
+ * disables metered APNs
*/
+ @SuppressLint("IntentName")
public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_DCFAILURE_STRING_ARRAY =
"carrier_default_actions_on_dcfailure_string_array";
/**
- * Defines carrier-specific actions which act upon
- * com.android.internal.telephony.CARRIER_SIGNAL_RESET, used for customization of the
- * default carrier app
+ * Defines carrier-specific actions which act upon CARRIER_SIGNAL_RESET,
+ * used for customization of the default carrier app.
* Format: "CARRIER_ACTION_IDX, ..."
* Where {@code CARRIER_ACTION_IDX} is an integer defined in
- * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
+ * com.android.carrierdefaultapp.CarrierActionUtils
* Example:
- * {@link com.android.carrierdefaultapp.CarrierActionUtils
- * #CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS clear all notifications on reset}
- * @hide
+ * com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS
+ * clears all notifications on reset
*/
+ @SuppressLint("IntentName")
public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET =
"carrier_default_actions_on_reset_string_array";
/**
* Defines carrier-specific actions which act upon
* com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE,
- * used for customization of the default carrier app
+ * used for customization of the default carrier app.
* Format:
* {
* "true : CARRIER_ACTION_IDX_1",
@@ -1688,17 +1657,17 @@
* }
* Where {@code true} is a boolean indicates default network available/unavailable
* Where {@code CARRIER_ACTION_IDX} is an integer defined in
- * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
+ * com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils
* Example:
- * {@link com.android.carrierdefaultapp.CarrierActionUtils
- * #CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER enable the app as the default URL handler}
- * @hide
+ * com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER
+ * enables the app as the default URL handler
*/
+ @SuppressLint("IntentName")
public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_DEFAULT_NETWORK_AVAILABLE =
"carrier_default_actions_on_default_network_available_string_array";
+
/**
- * Defines a list of acceptable redirection url for default carrier app
- * @hides
+ * Defines a list of acceptable redirection url for default carrier app.
*/
public static final String KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY =
"carrier_default_redirection_url_string_array";
@@ -1826,10 +1795,10 @@
/**
* Determines whether to enable enhanced call blocking feature on the device.
- * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED
- * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_PRIVATE
- * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_PAYPHONE
- * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNKNOWN
+ * android.provider.BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED
+ * android.provider.BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_PRIVATE
+ * android.provider.BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_PAYPHONE
+ * android.provider.BlockedNumberContract.SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNKNOWN
*
* <p>
* 1. For Single SIM(SS) device, it can be customized in both carrier_config_mccmnc.xml
@@ -1839,7 +1808,6 @@
* function is used regardless of SIM.
* <p>
* If {@code true} enable enhanced call blocking feature on the device, {@code false} otherwise.
- * @hide
*/
public static final String KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL =
"support_enhanced_call_blocking_bool";
@@ -1950,7 +1918,6 @@
/**
* Flag indicating whether the carrier supports call deflection for an incoming IMS call.
- * @hide
*/
public static final String KEY_CARRIER_ALLOW_DEFLECT_IMS_CALL_BOOL =
"carrier_allow_deflect_ims_call_bool";
@@ -2015,8 +1982,6 @@
/**
* Whether system apps are allowed to use fallback if carrier video call is not available.
* Defaults to {@code true}.
- *
- * @hide
*/
public static final String KEY_ALLOW_VIDEO_CALLING_FALLBACK_BOOL =
"allow_video_calling_fallback_bool";
@@ -2054,9 +2019,8 @@
"enhanced_4g_lte_title_variant_bool";
/**
- * The index indicates the carrier specified title string of Enahnce 4G LTE Mode settings.
+ * The index indicates the carrier specified title string of Enhanced 4G LTE Mode settings.
* Default value is 0, which indicates the default title string.
- * @hide
*/
public static final String KEY_ENHANCED_4G_LTE_TITLE_VARIANT_INT =
"enhanced_4g_lte_title_variant_int";
@@ -2100,15 +2064,13 @@
* {@link #KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL} is false. If
* {@link #KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL} is true, this
* configuration is ignored and roaming preference cannot be changed.
- * @hide
*/
public static final String KEY_EDITABLE_WFC_ROAMING_MODE_BOOL =
"editable_wfc_roaming_mode_bool";
/**
- * Flag specifying wether to show blocking pay phone option in blocked numbers screen. Only show
- * the option if payphone call presentation represents in the carrier's region.
- * @hide
+ * Flag specifying whether to show blocking pay phone option in blocked numbers screen.
+ * Only show the option if payphone call presentation is present in the carrier's region.
*/
public static final java.lang.String KEY_SHOW_BLOCKING_PAY_PHONE_OPTION_BOOL =
"show_blocking_pay_phone_option_bool";
@@ -2118,7 +2080,6 @@
* {@code false} - roaming preference can be selected separately from the home preference.
* {@code true} - roaming preference is the same as home preference and
* {@link #KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT} is used as the default value.
- * @hide
*/
public static final String KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL =
"use_wfc_home_network_mode_in_roaming_network_bool";
@@ -2146,7 +2107,6 @@
* while the device is registered over WFC. Default value is -1, which indicates
* that this notification is not pertinent for a particular carrier. We've added a delay
* to prevent false positives.
- * @hide
*/
public static final String KEY_EMERGENCY_NOTIFICATION_DELAY_INT =
"emergency_notification_delay_int";
@@ -2197,7 +2157,6 @@
/**
* Flag specifying whether to show an alert dialog for video call charges.
* By default this value is {@code false}.
- * @hide
*/
public static final String KEY_SHOW_VIDEO_CALL_CHARGES_ALERT_DIALOG_BOOL =
"show_video_call_charges_alert_dialog_bool";
@@ -2484,10 +2443,9 @@
/**
* Identifies if the key is available for WLAN or EPDG or both. The value is a bitmask.
* 0 indicates that neither EPDG or WLAN is enabled.
- * 1 indicates that key type {@link TelephonyManager#KEY_TYPE_EPDG} is enabled.
- * 2 indicates that key type {@link TelephonyManager#KEY_TYPE_WLAN} is enabled.
+ * 1 indicates that key type TelephonyManager#KEY_TYPE_EPDG is enabled.
+ * 2 indicates that key type TelephonyManager#KEY_TYPE_WLAN is enabled.
* 3 indicates that both are enabled.
- * @hide
*/
public static final String IMSI_KEY_AVAILABILITY_INT = "imsi_key_availability_int";
@@ -2505,7 +2463,6 @@
/**
* Flag specifying whether IMS registration state menu is shown in Status Info setting,
* default to false.
- * @hide
*/
public static final String KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL =
"show_ims_registration_status_bool";
@@ -2561,7 +2518,6 @@
/**
* The flag to disable the popup dialog which warns the user of data charges.
- * @hide
*/
public static final String KEY_DISABLE_CHARGE_INDICATION_BOOL =
"disable_charge_indication_bool";
@@ -2626,15 +2582,13 @@
/**
* Determines whether any carrier has been identified and its specific config has been applied,
* default to false.
- * @hide
*/
public static final String KEY_CARRIER_CONFIG_APPLIED_BOOL = "carrier_config_applied_bool";
/**
* Determines whether we should show a warning asking the user to check with their carrier
- * on pricing when the user enabled data roaming.
+ * on pricing when the user enabled data roaming,
* default to false.
- * @hide
*/
public static final String KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL =
"check_pricing_with_carrier_data_roaming_bool";
@@ -2786,10 +2740,10 @@
* Specifies a carrier-defined {@link android.telecom.CallRedirectionService} which Telecom
* will bind to for outgoing calls. An empty string indicates that no carrier-defined
* {@link android.telecom.CallRedirectionService} is specified.
- * @hide
*/
public static final String KEY_CALL_REDIRECTION_SERVICE_COMPONENT_NAME_STRING =
"call_redirection_service_component_name_string";
+
/**
* Support for the original string display of CDMA MO call.
* By default, it is disabled.
@@ -2902,8 +2856,8 @@
"call_waiting_service_class_int";
/**
- * This configuration allow the system UI to display different 5G icon for different 5G
- * scenario.
+ * This configuration allows the system UI to display different 5G icons for different 5G
+ * scenarios.
*
* There are five 5G scenarios:
* 1. connected_mmwave: device currently connected to 5G cell as the secondary cell and using
@@ -2920,24 +2874,22 @@
* 5G cell as a secondary cell) but the use of 5G is restricted.
*
* The configured string contains multiple key-value pairs separated by comma. For each pair,
- * the key and value is separated by a colon. The key is corresponded to a 5G status above and
+ * the key and value are separated by a colon. The key corresponds to a 5G status above and
* the value is the icon name. Use "None" as the icon name if no icon should be shown in a
* specific 5G scenario. If the scenario is "None", config can skip this key and value.
*
* Icon name options: "5G_Plus", "5G".
*
* Here is an example:
- * UE want to display 5G_Plus icon for scenario#1, and 5G icon for scenario#2; otherwise no
+ * UE wants to display 5G_Plus icon for scenario#1, and 5G icon for scenario#2; otherwise not
* define.
* The configuration is: "connected_mmwave:5G_Plus,connected:5G"
- *
- * @hide
*/
public static final String KEY_5G_ICON_CONFIGURATION_STRING =
"5g_icon_configuration_string";
/**
- * Timeout in second for displaying 5G icon, default value is 0 which means the timer is
+ * Timeout in seconds for displaying 5G icon, default value is 0 which means the timer is
* disabled.
*
* System UI will show the 5G icon and start a timer with the timeout from this config when the
@@ -2946,8 +2898,6 @@
*
* If 5G is reacquired during this timer, the timer is canceled and restarted when 5G is next
* lost. Allows us to momentarily lose 5G without blinking the icon.
- *
- * @hide
*/
public static final String KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT =
"5g_icon_display_grace_period_sec_int";
@@ -3112,8 +3062,6 @@
* signal bar of primary network. By default it will be false, meaning whenever data
* is going over opportunistic network, signal bar will reflect signal strength and rat
* icon of that network.
- *
- * @hide
*/
public static final String KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN =
"always_show_primary_signal_bar_in_opportunistic_network_boolean";
@@ -3335,8 +3283,6 @@
/**
* Determines whether wifi calling location privacy policy is shown.
- *
- * @hide
*/
public static final String KEY_SHOW_WFC_LOCATION_PRIVACY_POLICY_BOOL =
"show_wfc_location_privacy_policy_bool";
@@ -3447,8 +3393,8 @@
"support_wps_over_ims_bool";
/**
- * Holds the list of carrier certificate hashes. Note that each carrier has its own certificates
- * @hide
+ * Holds the list of carrier certificate hashes.
+ * Note that each carrier has its own certificates.
*/
public static final String KEY_CARRIER_CERTIFICATE_STRING_ARRAY =
"carrier_certificate_string_array";
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 1dbc8b1..8ed4ee5 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -780,7 +780,11 @@
"Invalid pdu format. format must be either 3gpp or 3gpp2");
}
try {
- ISms iSms = TelephonyManager.getSmsService();
+ ISms iSms = ISms.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSmsServiceRegisterer()
+ .get());
if (iSms != null) {
iSms.injectSmsPduForSubscriber(
getSubscriptionId(), pdu, format, receivedIntent);
@@ -1603,7 +1607,7 @@
* the service does not exist.
*/
private static ISms getISmsServiceOrThrow() {
- ISms iSms = TelephonyManager.getSmsService();
+ ISms iSms = getISmsService();
if (iSms == null) {
throw new UnsupportedOperationException("Sms is not supported");
}
@@ -1611,7 +1615,11 @@
}
private static ISms getISmsService() {
- return TelephonyManager.getSmsService();
+ return ISms.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSmsServiceRegisterer()
+ .get());
}
/**
@@ -2045,7 +2053,11 @@
public boolean isSMSPromptEnabled() {
ISms iSms = null;
try {
- iSms = TelephonyManager.getSmsService();
+ iSms = ISms.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSmsServiceRegisterer()
+ .get());
return iSms.isSMSPromptEnabled();
} catch (RemoteException ex) {
return false;
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index cb4462f..36f541f 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -16,8 +16,6 @@
package android.telephony;
-import com.android.telephony.Rlog;
-
import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
@@ -67,6 +65,7 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.util.HandlerExecutor;
import com.android.internal.util.Preconditions;
+import com.android.telephony.Rlog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -1146,7 +1145,11 @@
SubscriptionInfo subInfo = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1180,7 +1183,11 @@
SubscriptionInfo result = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1214,7 +1221,11 @@
SubscriptionInfo result = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIndex,
mContext.getOpPackageName(), mContext.getFeatureId());
@@ -1238,7 +1249,11 @@
List<SubscriptionInfo> result = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getAllSubInfoList(mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1319,7 +1334,11 @@
List<SubscriptionInfo> activeList = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
activeList = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1370,7 +1389,11 @@
List<SubscriptionInfo> result = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1409,7 +1432,11 @@
List<SubscriptionInfo> result = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getAccessibleSubscriptionInfoList(mContext.getOpPackageName());
}
@@ -1438,7 +1465,11 @@
public void requestEmbeddedSubscriptionInfoListRefresh() {
int cardId = TelephonyManager.from(mContext).getCardIdForDefaultEuicc();
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.requestEmbeddedSubscriptionInfoListRefresh(cardId);
}
@@ -1467,7 +1498,11 @@
@SystemApi
public void requestEmbeddedSubscriptionInfoListRefresh(int cardId) {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.requestEmbeddedSubscriptionInfoListRefresh(cardId);
}
@@ -1488,7 +1523,11 @@
int result = 0;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getAllSubInfoCount(mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1517,7 +1556,11 @@
int result = 0;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getActiveSubInfoCount(mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -1538,7 +1581,11 @@
int result = 0;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getActiveSubInfoCountMax();
}
@@ -1595,7 +1642,11 @@
}
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub == null) {
Log.e(LOG_TAG, "[addSubscriptionInfoRecord]- ISub service is null");
return;
@@ -1629,7 +1680,11 @@
}
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub == null) {
Log.e(LOG_TAG, "[removeSubscriptionInfoRecord]- ISub service is null");
return;
@@ -1732,7 +1787,11 @@
int result = INVALID_SIM_SLOT_INDEX;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getSlotIndex(subscriptionId);
}
@@ -1766,7 +1825,11 @@
int[] subId = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subId = iSub.getSubId(slotIndex);
}
@@ -1790,7 +1853,11 @@
int result = INVALID_PHONE_INDEX;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getPhoneId(subId);
}
@@ -1824,7 +1891,11 @@
int subId = INVALID_SUBSCRIPTION_ID;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subId = iSub.getDefaultSubId();
}
@@ -1847,7 +1918,11 @@
int subId = INVALID_SUBSCRIPTION_ID;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subId = iSub.getDefaultVoiceSubId();
}
@@ -1877,7 +1952,11 @@
public void setDefaultVoiceSubscriptionId(int subscriptionId) {
if (VDBG) logd("setDefaultVoiceSubId sub id = " + subscriptionId);
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.setDefaultVoiceSubId(subscriptionId);
}
@@ -1925,7 +2004,11 @@
int subId = INVALID_SUBSCRIPTION_ID;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subId = iSub.getDefaultSmsSubId();
}
@@ -1951,7 +2034,11 @@
public void setDefaultSmsSubId(int subscriptionId) {
if (VDBG) logd("setDefaultSmsSubId sub id = " + subscriptionId);
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.setDefaultSmsSubId(subscriptionId);
}
@@ -1989,7 +2076,11 @@
int subId = INVALID_SUBSCRIPTION_ID;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subId = iSub.getDefaultDataSubId();
}
@@ -2015,7 +2106,11 @@
public void setDefaultDataSubId(int subscriptionId) {
if (VDBG) logd("setDataSubscription sub id = " + subscriptionId);
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.setDefaultDataSubId(subscriptionId);
}
@@ -2046,7 +2141,11 @@
/** @hide */
public void clearSubscriptionInfo() {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.clearSubInfo();
}
@@ -2140,10 +2239,9 @@
@UnsupportedAppUsage
public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId) {
if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
- intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
intent.putExtra(EXTRA_SLOT_INDEX, phoneId);
intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
+ putSubscriptionIdExtra(intent, subId);
}
/**
@@ -2182,7 +2280,11 @@
*/
public @NonNull int[] getActiveSubscriptionIdList(boolean visibleOnly) {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
int[] subId = iSub.getActiveSubIdList(visibleOnly);
if (subId != null) return subId;
@@ -2233,7 +2335,11 @@
int simState = TelephonyManager.SIM_STATE_UNKNOWN;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
simState = iSub.getSimStateForSlotIndex(slotIndex);
}
@@ -2252,7 +2358,11 @@
*/
public static void setSubscriptionProperty(int subId, String propKey, String propValue) {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.setSubscriptionProperty(subId, propKey, propValue);
}
@@ -2272,7 +2382,11 @@
Context context) {
String resultValue = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
resultValue = iSub.getSubscriptionProperty(subId, propKey,
context.getOpPackageName(), context.getFeatureId());
@@ -2414,7 +2528,11 @@
@UnsupportedAppUsage
public boolean isActiveSubId(int subId) {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
return iSub.isActiveSubId(subId, mContext.getOpPackageName(),
mContext.getFeatureId());
@@ -2717,7 +2835,11 @@
@TelephonyManager.SetOpportunisticSubscriptionResult Consumer<Integer> callback) {
if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId);
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub == null) return;
ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
@@ -2760,7 +2882,11 @@
public int getPreferredDataSubscriptionId() {
int preferredSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
preferredSubId = iSub.getPreferredDataSubscriptionId();
}
@@ -2791,7 +2917,11 @@
List<SubscriptionInfo> subInfoList = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subInfoList = iSub.getOpportunisticSubscriptions(contextPkg, contextFeature);
}
@@ -2892,7 +3022,11 @@
ParcelUuid groupUuid = null;
int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray();
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
groupUuid = iSub.createSubscriptionGroup(subIdArray, pkgForDebug);
} else {
@@ -2942,7 +3076,11 @@
int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray();
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.addSubscriptionsIntoGroup(subIdArray, groupUuid, pkgForDebug);
} else {
@@ -2994,7 +3132,11 @@
int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray();
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
iSub.removeSubscriptionsFromGroup(subIdArray, groupUuid, pkgForDebug);
} else {
@@ -3039,7 +3181,11 @@
List<SubscriptionInfo> result = null;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = iSub.getSubscriptionsInGroup(groupUuid, contextPkg, contextFeature);
} else {
@@ -3152,7 +3298,11 @@
logd("setSubscriptionActivated subId= " + subscriptionId + " enable " + enable);
}
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
return iSub.setSubscriptionEnabled(enable, subscriptionId);
}
@@ -3241,7 +3391,11 @@
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isSubscriptionEnabled(int subscriptionId) {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
return iSub.isSubscriptionEnabled(subscriptionId);
}
@@ -3264,7 +3418,11 @@
int subId = INVALID_SUBSCRIPTION_ID;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
subId = iSub.getEnabledSubscriptionId(slotIndex);
}
@@ -3290,7 +3448,11 @@
int result = 0;
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
result = helper.callMethod(iSub);
}
@@ -3313,7 +3475,11 @@
*/
public static int getActiveDataSubscriptionId() {
try {
- ISub iSub = TelephonyManager.getSubscriptionService();
+ ISub iSub = ISub.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getSubscriptionServiceRegisterer()
+ .get());
if (iSub != null) {
return iSub.getActiveDataSubscriptionId();
}
@@ -3321,4 +3487,19 @@
}
return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
+
+ /**
+ * Helper method that puts a subscription id on an intent with the constants:
+ * PhoneConstant.SUBSCRIPTION_KEY and SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX.
+ * Both constants are used to support backwards compatibility. Once we know we got all places,
+ * we can remove PhoneConstants.SUBSCRIPTION_KEY.
+ * @param intent Intent to put sub id on.
+ * @param subId SubscriptionId to put on intent.
+ *
+ * @hide
+ */
+ public static void putSubscriptionIdExtra(Intent intent, int subId) {
+ intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
+ intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
+ }
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d15a531..0ffeccf 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -57,7 +57,6 @@
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
-import android.os.IBinder;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
@@ -95,15 +94,12 @@
import android.util.Pair;
import com.android.ims.internal.IImsServiceFeatureCallback;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.CellNetworkScanResult;
import com.android.internal.telephony.INumberVerificationCallback;
import com.android.internal.telephony.IOns;
import com.android.internal.telephony.IPhoneSubInfo;
import com.android.internal.telephony.ISetOpportunisticDataCallback;
-import com.android.internal.telephony.ISms;
-import com.android.internal.telephony.ISub;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
@@ -303,21 +299,6 @@
private SubscriptionManager mSubscriptionManager;
private TelephonyScanManager mTelephonyScanManager;
- /** Cached service handles, cleared by resetServiceHandles() at death */
- private static final Object sCacheLock = new Object();
-
- /** @hide */
- private static boolean sServiceHandleCacheEnabled = true;
-
- @GuardedBy("sCacheLock")
- private static IPhoneSubInfo sIPhoneSubInfo;
- @GuardedBy("sCacheLock")
- private static ISub sISub;
- @GuardedBy("sCacheLock")
- private static ISms sISms;
- @GuardedBy("sCacheLock")
- private static final DeathRecipient sServiceDeath = new DeathRecipient();
-
/** Enum indicating multisim variants
* DSDS - Dual SIM Dual Standby
* DSDA - Dual SIM Dual Active
@@ -1463,7 +1444,8 @@
/**
* <p>Broadcast Action: The emergency callback mode is changed.
* <ul>
- * <li><em>phoneinECMState</em> - A boolean value,true=phone in ECM, false=ECM off</li>
+ * <li><em>EXTRA_PHONE_IN_ECM_STATE</em> - A boolean value,true=phone in ECM,
+ * false=ECM off</li>
* </ul>
* <p class="note">
* You can <em>not</em> receive this through components declared
@@ -1473,12 +1455,25 @@
*
* <p class="note">This is a protected intent that can only be sent by the system.
*
+ * @see #EXTRA_PHONE_IN_ECM_STATE
+ *
* @hide
*/
@SystemApi
@SuppressLint("ActionValue")
- public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
- = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED";
+ public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED =
+ "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED";
+
+
+ /**
+ * Extra included in {@link #ACTION_EMERGENCY_CALLBACK_MODE_CHANGED}.
+ * Indicates whether the phone is in an emergency phone state.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_PHONE_IN_ECM_STATE =
+ "android.telephony.extra.PHONE_IN_ECM_STATE";
/**
* <p>Broadcast Action: when data connections get redirected with validation failure.
@@ -1670,8 +1665,8 @@
/**
* <p>Broadcast Action: The emergency call state is changed.
* <ul>
- * <li><em>phoneInEmergencyCall</em> - A boolean value, true if phone in emergency call,
- * false otherwise</li>
+ * <li><em>EXTRA_PHONE_IN_EMERGENCY_CALL</em> - A boolean value, true if phone in emergency
+ * call, false otherwise</li>
* </ul>
* <p class="note">
* You can <em>not</em> receive this through components declared
@@ -1681,12 +1676,25 @@
*
* <p class="note">This is a protected intent that can only be sent by the system.
*
+ * @see #EXTRA_PHONE_IN_EMERGENCY_CALL
+ *
* @hide
*/
@SystemApi
@SuppressLint("ActionValue")
- public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED
- = "android.intent.action.EMERGENCY_CALL_STATE_CHANGED";
+ public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED =
+ "android.intent.action.EMERGENCY_CALL_STATE_CHANGED";
+
+
+ /**
+ * Extra included in {@link #ACTION_EMERGENCY_CALL_STATE_CHANGED}.
+ * It indicates whether the phone is making an emergency call.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_PHONE_IN_EMERGENCY_CALL =
+ "android.telephony.extra.PHONE_IN_EMERGENCY_CALL";
/**
* <p>Broadcast Action: It indicates the Emergency callback mode blocks datacall/sms
@@ -1699,8 +1707,8 @@
* @hide
*/
@SystemApi
- public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS
- = "android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS";
+ public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS =
+ "android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS";
/**
* Broadcast Action: The default data subscription has changed in a multi-SIM device.
@@ -1713,8 +1721,8 @@
*/
@SystemApi
@SuppressLint("ActionValue")
- public static final String ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED
- = "android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED";
+ public static final String ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED =
+ "android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED";
/**
* Broadcast Action: The default voice subscription has changed in a mult-SIm device.
@@ -1727,8 +1735,8 @@
*/
@SystemApi
@SuppressLint("ActionValue")
- public static final String ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED
- = "android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED";
+ public static final String ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED =
+ "android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED";
/**
* Broadcast Action: This triggers a client initiated OMA-DM session to the OMA server.
@@ -1741,8 +1749,8 @@
*/
@SystemApi
@SuppressLint("ActionValue")
- public static final String ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE
- = "com.android.omadm.service.CONFIGURATION_UPDATE";
+ public static final String ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE =
+ "com.android.omadm.service.CONFIGURATION_UPDATE";
//
//
@@ -1866,7 +1874,7 @@
public String getDeviceId(int slotIndex) {
// FIXME this assumes phoneId == slotIndex
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getDeviceIdForPhone(slotIndex, mContext.getOpPackageName(),
@@ -2120,7 +2128,7 @@
private String getNaiBySubscriberId(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
String nai = info.getNaiForSubscriber(subId, mContext.getOpPackageName(),
@@ -3809,7 +3817,7 @@
@UnsupportedAppUsage
public String getSimSerialNumber(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName(),
@@ -4083,7 +4091,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public String getSubscriberId(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getSubscriberIdForSubscriber(subId, mContext.getOpPackageName(),
@@ -4119,7 +4127,7 @@
@Nullable
public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(@KeyType int keyType) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null) {
Rlog.e(TAG,"IMSI error: Subscriber Info is null");
return null;
@@ -4162,7 +4170,7 @@
@SystemApi
public void resetCarrierKeysForImsiEncryption() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null) {
Rlog.e(TAG, "IMSI error: Subscriber Info is null");
if (!isSystemProcess()) {
@@ -4227,7 +4235,7 @@
*/
public void setCarrierInfoForImsiEncryption(ImsiEncryptionInfo imsiEncryptionInfo) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null) return;
info.setCarrierInfoForImsiEncryption(mSubId, mContext.getOpPackageName(),
imsiEncryptionInfo);
@@ -4251,7 +4259,7 @@
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public String getGroupIdLevel1() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getGroupIdLevel1ForSubscriber(getSubId(), mContext.getOpPackageName(),
@@ -4275,7 +4283,7 @@
@UnsupportedAppUsage
public String getGroupIdLevel1(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getGroupIdLevel1ForSubscriber(subId, mContext.getOpPackageName(),
@@ -4338,7 +4346,7 @@
return number;
}
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getLine1NumberForSubscriber(subId, mContext.getOpPackageName(),
@@ -4429,7 +4437,7 @@
return alphaTag;
}
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getLine1AlphaTagForSubscriber(subId, getOpPackageName(),
@@ -4517,7 +4525,7 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public String getMsisdn(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getMsisdnForSubscriber(subId, getOpPackageName(), getFeatureId());
@@ -4551,7 +4559,7 @@
@UnsupportedAppUsage
public String getVoiceMailNumber(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getVoiceMailNumberForSubscriber(subId, getOpPackageName(),
@@ -5150,7 +5158,7 @@
@UnsupportedAppUsage
public String getVoiceMailAlphaTag(int subId) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getVoiceMailAlphaTagForSubscriber(subId, getOpPackageName(),
@@ -5198,7 +5206,7 @@
@UnsupportedAppUsage
public String getIsimImpi() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
//get the Isim Impi based on subId
@@ -5225,7 +5233,7 @@
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getIsimDomain() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
//get the Isim Domain based on subId
@@ -5249,7 +5257,7 @@
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String[] getIsimImpu() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
//get the Isim Impu based on subId
@@ -5262,6 +5270,19 @@
}
}
+ /**
+ * @hide
+ */
+ @UnsupportedAppUsage
+ private IPhoneSubInfo getSubscriberInfo() {
+ // get it each time because that process crashes a lot
+ return IPhoneSubInfo.Stub.asInterface(
+ TelephonyFrameworkInitializer
+ .getTelephonyServiceManager()
+ .getPhoneSubServiceRegisterer()
+ .get());
+ }
+
/**
* Device call state: No activity.
*/
@@ -7012,7 +7033,7 @@
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getIsimIst() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
//get the Isim Ist based on subId
@@ -7034,7 +7055,7 @@
@UnsupportedAppUsage
public String[] getIsimPcscf() {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
//get the Isim Pcscf based on subId
@@ -7115,7 +7136,7 @@
@UnsupportedAppUsage
public String getIccAuthentication(int subId, int appType, int authType, String data) {
try {
- IPhoneSubInfo info = getSubscriberInfoService();
+ IPhoneSubInfo info = getSubscriberInfo();
if (info == null)
return null;
return info.getIccSimChallengeResponse(subId, appType, authType, data);
@@ -12391,150 +12412,4 @@
}
return false;
}
-
- private static class DeathRecipient implements IBinder.DeathRecipient {
- @Override
- public void binderDied() {
- resetServiceCache();
- }
- }
-
- /**
- * Reset everything in the service cache; if one handle died then they are
- * all probably broken.
- * @hide
- */
- private static void resetServiceCache() {
- synchronized (sCacheLock) {
- if (sISub != null) {
- sISub.asBinder().unlinkToDeath(sServiceDeath, 0);
- sISub = null;
- }
- if (sISms != null) {
- sISms.asBinder().unlinkToDeath(sServiceDeath, 0);
- sISms = null;
- }
- if (sIPhoneSubInfo != null) {
- sIPhoneSubInfo.asBinder().unlinkToDeath(sServiceDeath, 0);
- sIPhoneSubInfo = null;
- }
- }
- }
-
- /**
- * @hide
- */
- static IPhoneSubInfo getSubscriberInfoService() {
- if (!sServiceHandleCacheEnabled) {
- return IPhoneSubInfo.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getPhoneSubServiceRegisterer()
- .get());
- }
-
- if (sIPhoneSubInfo == null) {
- IPhoneSubInfo temp = IPhoneSubInfo.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getPhoneSubServiceRegisterer()
- .get());
- synchronized (sCacheLock) {
- if (sIPhoneSubInfo == null && temp != null) {
- try {
- sIPhoneSubInfo = temp;
- sIPhoneSubInfo.asBinder().linkToDeath(sServiceDeath, 0);
- } catch (Exception e) {
- // something has gone horribly wrong
- sIPhoneSubInfo = null;
- }
- }
- }
- }
- return sIPhoneSubInfo;
- }
-
- /**
- * @hide
- */
- static ISub getSubscriptionService() {
- if (!sServiceHandleCacheEnabled) {
- return ISub.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getSubscriptionServiceRegisterer()
- .get());
- }
-
- if (sISub == null) {
- ISub temp = ISub.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getSubscriptionServiceRegisterer()
- .get());
- synchronized (sCacheLock) {
- if (sISub == null && temp != null) {
- try {
- sISub = temp;
- sISub.asBinder().linkToDeath(sServiceDeath, 0);
- } catch (Exception e) {
- // something has gone horribly wrong
- sISub = null;
- }
- }
- }
- }
- return sISub;
- }
-
- /**
- * @hide
- */
- static ISms getSmsService() {
- if (!sServiceHandleCacheEnabled) {
- return ISms.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getSmsServiceRegisterer()
- .get());
- }
-
- if (sISms == null) {
- ISms temp = ISms.Stub.asInterface(
- TelephonyFrameworkInitializer
- .getTelephonyServiceManager()
- .getSmsServiceRegisterer()
- .get());
- synchronized (sCacheLock) {
- if (sISms == null && temp != null) {
- try {
- sISms = temp;
- sISms.asBinder().linkToDeath(sServiceDeath, 0);
- } catch (Exception e) {
- // something has gone horribly wrong
- sISms = null;
- }
- }
- }
- }
- return sISms;
- }
-
- /**
- * Disables service handle caching for tests that utilize mock services.
- * @hide
- */
- @VisibleForTesting
- public static void disableServiceHandleCaching() {
- sServiceHandleCacheEnabled = false;
- }
-
- /**
- * Reenables service handle caching.
- * @hide
- */
- @VisibleForTesting
- public static void enableServiceHandleCaching() {
- sServiceHandleCacheEnabled = true;
- }
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 51701eb..db8c845 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -100,9 +100,6 @@
public static final String DATA_APN_TYPE_KEY = "apnType";
public static final String DATA_APN_KEY = "apn";
- public static final String PHONE_IN_ECM_STATE = "phoneinECMState";
- public static final String PHONE_IN_EMERGENCY_CALL = "phoneInEmergencyCall";
-
/**
* Return codes for supplyPinReturnResult and
* supplyPukReturnResult APIs
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index 0ab5c97..11d5b25 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -222,7 +222,7 @@
@Override
public Network getNetwork() {
- return new Network(mNetworkAgent.netId);
+ return mNetworkAgent.network;
}
public void expectPreventReconnectReceived(long timeoutMs) {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index b2d363e..1901a1d 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -575,7 +575,7 @@
}
};
- assertEquals(na.netId, nmNetworkCaptor.getValue().netId);
+ assertEquals(na.network.netId, nmNetworkCaptor.getValue().netId);
mNmCallbacks = nmCbCaptor.getValue();
mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index 9e915ae..e863266 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -35,7 +35,6 @@
import android.net.IDnsResolver;
import android.net.INetd;
import android.net.Network;
-import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkProvider;
@@ -75,7 +74,6 @@
@Mock INetd mNetd;
@Mock INetworkManagementService mNMS;
@Mock Context mCtx;
- @Mock NetworkAgentConfig mAgentConfig;
@Mock NetworkNotificationManager mNotifier;
@Mock Resources mResources;
@@ -358,7 +356,7 @@
NetworkScore ns = new NetworkScore();
ns.putIntExtension(NetworkScore.LEGACY_SCORE, 50);
NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null,
- caps, ns, mCtx, null, mAgentConfig, mConnService, mNetd, mDnsResolver, mNMS,
+ caps, ns, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS,
NetworkProvider.ID_NONE);
nai.everValidated = true;
return nai;
diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
index cf70f5d..9b24887 100644
--- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
+++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
@@ -63,7 +63,6 @@
static final int NETID = 42;
@Mock ConnectivityService mConnectivity;
- @Mock NetworkAgentConfig mAgentConfig;
@Mock IDnsResolver mDnsResolver;
@Mock INetd mNetd;
@Mock INetworkManagementService mNms;
@@ -72,6 +71,7 @@
TestLooper mLooper;
Handler mHandler;
+ NetworkAgentConfig mAgentConfig = new NetworkAgentConfig();
Nat464Xlat makeNat464Xlat() {
return new Nat464Xlat(mNai, mNetd, mDnsResolver, mNms) {
diff --git a/wifi/Android.bp b/wifi/Android.bp
index 6326f14..70c9bef 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -50,6 +50,8 @@
"//frameworks/opt/net/wifi/libs/WifiTrackerLib/tests",
"//external/robolectric-shadows:__subpackages__",
+ "//frameworks/base/packages/SettingsLib/tests/integ",
+ "//external/sl4a:__subpackages__",
]
// wifi-service needs pre-jarjared version of framework-wifi so it can reference copied utility
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index c6aca07..3413305 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -23,6 +23,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -793,10 +795,19 @@
}
}
- /** empty scan result
+ /**
+ * Construct an empty scan result.
*
- * {@hide}
- * */
+ * Test code has a need to construct a ScanResult in a specific state.
+ * (Note that mocking using Mockito does not work if the object needs to be parceled and
+ * unparceled.)
+ * Export a @SystemApi default constructor to allow tests to construct an empty ScanResult
+ * object. The test can then directly set the fields it cares about.
+ *
+ * @hide
+ */
+ @SystemApi
+ @VisibleForTesting
public ScanResult() {
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index f4c5b91..ee2b575 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -39,6 +39,8 @@
import android.util.Log;
import android.util.SparseArray;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
@@ -1208,22 +1210,27 @@
*/
@SystemApi
public static class NetworkSelectionStatus {
- // Quality Network Selection Status enable, temporary disabled, permanently disabled
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "NETWORK_SELECTION_",
+ value = {
+ NETWORK_SELECTION_ENABLED,
+ NETWORK_SELECTION_TEMPORARY_DISABLED,
+ NETWORK_SELECTION_PERMANENTLY_DISABLED})
+ public @interface NetworkEnabledStatus {}
/**
- * This network is allowed to join Quality Network Selection
- * @hide
+ * This network will be considered as a potential candidate to connect to during network
+ * selection.
*/
public static final int NETWORK_SELECTION_ENABLED = 0;
/**
- * network was temporary disabled. Can be re-enabled after a time period expire
- * @hide
+ * This network was temporary disabled. May be re-enabled after a time out.
*/
- public static final int NETWORK_SELECTION_TEMPORARY_DISABLED = 1;
+ public static final int NETWORK_SELECTION_TEMPORARY_DISABLED = 1;
/**
- * network was permanently disabled.
- * @hide
+ * This network was permanently disabled.
*/
- public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED = 2;
+ public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED = 2;
/**
* Maximum Network selection status
* @hide
@@ -1455,6 +1462,7 @@
* Network selection status, should be in one of three status: enable, temporaily disabled
* or permanently disabled
*/
+ @NetworkEnabledStatus
private int mStatus;
/**
@@ -1635,6 +1643,56 @@
}
/**
+ * NetworkSelectionStatus exports an immutable public API.
+ * However, test code has a need to construct a NetworkSelectionStatus in a specific state.
+ * (Note that mocking using Mockito does not work if the object needs to be parceled and
+ * unparceled.)
+ * Export a @SystemApi Builder to allow tests to construct a NetworkSelectionStatus object
+ * in the desired state, without sacrificing NetworkSelectionStatus's immutability.
+ */
+ @VisibleForTesting
+ public static final class Builder {
+ private final NetworkSelectionStatus mNetworkSelectionStatus =
+ new NetworkSelectionStatus();
+
+ /**
+ * Set the current network selection status.
+ * One of:
+ * {@link #NETWORK_SELECTION_ENABLED},
+ * {@link #NETWORK_SELECTION_TEMPORARY_DISABLED},
+ * {@link #NETWORK_SELECTION_PERMANENTLY_DISABLED}
+ * @see NetworkSelectionStatus#getNetworkSelectionStatus()
+ */
+ @NonNull
+ public Builder setNetworkSelectionStatus(@NetworkEnabledStatus int status) {
+ mNetworkSelectionStatus.setNetworkSelectionStatus(status);
+ return this;
+ }
+
+ /**
+ *
+ * Set the current network's disable reason.
+ * One of the {@link #NETWORK_SELECTION_ENABLE} or DISABLED_* constants.
+ * e.g. {@link #DISABLED_ASSOCIATION_REJECTION}.
+ * @see NetworkSelectionStatus#getNetworkSelectionDisableReason()
+ */
+ @NonNull
+ public Builder setNetworkSelectionDisableReason(
+ @NetworkSelectionDisableReason int reason) {
+ mNetworkSelectionStatus.setNetworkSelectionDisableReason(reason);
+ return this;
+ }
+
+ /**
+ * Build a NetworkSelectionStatus object.
+ */
+ @NonNull
+ public NetworkSelectionStatus build() {
+ return mNetworkSelectionStatus;
+ }
+ }
+
+ /**
* Get the network disable reason string for a reason code (for debugging).
* @param reason specific error reason. One of the {@link #NETWORK_SELECTION_ENABLE} or
* DISABLED_* constants e.g. {@link #DISABLED_ASSOCIATION_REJECTION}.
@@ -1660,10 +1718,13 @@
}
/**
- * get current network network selection status
- * @return return current network network selection status
- * @hide
+ * Get the current network network selection status.
+ * One of:
+ * {@link #NETWORK_SELECTION_ENABLED},
+ * {@link #NETWORK_SELECTION_TEMPORARY_DISABLED},
+ * {@link #NETWORK_SELECTION_PERMANENTLY_DISABLED}
*/
+ @NetworkEnabledStatus
public int getNetworkSelectionStatus() {
return mStatus;
}
@@ -1965,10 +2026,11 @@
}
/**
- * Set the network selection status
+ * Set the network selection status.
* @hide
*/
- public void setNetworkSelectionStatus(NetworkSelectionStatus status) {
+ @SystemApi
+ public void setNetworkSelectionStatus(@NonNull NetworkSelectionStatus status) {
mNetworkSelectionStatus = status;
}
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 41f7c6e..5edcc2d 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -1028,8 +1028,10 @@
}
/**
- * @hide
+ * Get the client private key as supplied in {@link #setClientKeyEntryWithCertificateChain}, or
+ * null if unset.
*/
+ @Nullable
public PrivateKey getClientPrivateKey() {
return mClientPrivateKey;
}
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 62337cb..51b15af 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -17,6 +17,7 @@
package android.net.wifi;
import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
@@ -27,6 +28,8 @@
import android.os.Parcelable;
import android.text.TextUtils;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -356,6 +359,72 @@
}
}
+ /**
+ * WifiInfo exports an immutable public API.
+ * However, test code has a need to construct a WifiInfo in a specific state.
+ * (Note that mocking using Mockito does not work if the object needs to be parceled and
+ * unparceled.)
+ * Export a @SystemApi Builder to allow tests to construct a WifiInfo object
+ * in the desired state, without sacrificing WifiInfo's immutability.
+ *
+ * @hide
+ */
+ // This builder was not made public to reduce confusion for external developers as there are
+ // no legitimate uses for this builder except for testing.
+ @SystemApi
+ @VisibleForTesting
+ public static final class Builder {
+ private final WifiInfo mWifiInfo = new WifiInfo();
+
+ /**
+ * Set the SSID, in the form of a raw byte array.
+ * @see WifiInfo#getSSID()
+ */
+ @NonNull
+ public Builder setSsid(@NonNull byte[] ssid) {
+ mWifiInfo.setSSID(WifiSsid.createFromByteArray(ssid));
+ return this;
+ }
+
+ /**
+ * Set the BSSID.
+ * @see WifiInfo#getBSSID()
+ */
+ @NonNull
+ public Builder setBssid(@NonNull String bssid) {
+ mWifiInfo.setBSSID(bssid);
+ return this;
+ }
+
+ /**
+ * Set the RSSI, in dBm.
+ * @see WifiInfo#getRssi()
+ */
+ @NonNull
+ public Builder setRssi(int rssi) {
+ mWifiInfo.setRssi(rssi);
+ return this;
+ }
+
+ /**
+ * Set the network ID.
+ * @see WifiInfo#getNetworkId()
+ */
+ @NonNull
+ public Builder setNetworkId(int networkId) {
+ mWifiInfo.setNetworkId(networkId);
+ return this;
+ }
+
+ /**
+ * Build a WifiInfo object.
+ */
+ @NonNull
+ public WifiInfo build() {
+ return mWifiInfo;
+ }
+ }
+
/** @hide */
public void setSSID(WifiSsid wifiSsid) {
mWifiSsid = wifiSsid;
diff --git a/wifi/tests/Android.bp b/wifi/tests/Android.bp
new file mode 100644
index 0000000..6a39959
--- /dev/null
+++ b/wifi/tests/Android.bp
@@ -0,0 +1,50 @@
+// 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.
+
+// Make test APK
+// ============================================================
+
+android_test {
+ name: "FrameworksWifiApiTests",
+
+ defaults: ["framework-wifi-test-defaults"],
+
+ srcs: ["**/*.java"],
+
+ jacoco: {
+ include_filter: ["android.net.wifi.*"],
+ // TODO(b/147521214) need to exclude test classes
+ exclude_filter: [],
+ },
+
+ static_libs: [
+ "androidx.test.rules",
+ "core-test-rules",
+ "guava",
+ "mockito-target-minus-junit4",
+ "net-tests-utils",
+ "frameworks-base-testutils",
+ "truth-prebuilt",
+ ],
+
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+
+ test_suites: [
+ "device-tests",
+ "mts",
+ ],
+}
diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk
deleted file mode 100644
index d2c385b4..0000000
--- a/wifi/tests/Android.mk
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright (C) 2016 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-# Make test APK
-# ============================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-# This list is generated from the java source files in this module
-# The list is a comma separated list of class names with * matching zero or more characters.
-# Example:
-# Input files: src/com/android/server/wifi/Test.java src/com/android/server/wifi/AnotherTest.java
-# Generated exclude list: com.android.server.wifi.Test*,com.android.server.wifi.AnotherTest*
-
-# Filter all src files to just java files
-local_java_files := $(filter %.java,$(LOCAL_SRC_FILES))
-# Transform java file names into full class names.
-# This only works if the class name matches the file name and the directory structure
-# matches the package.
-local_classes := $(subst /,.,$(patsubst src/%.java,%,$(local_java_files)))
-# Convert class name list to jacoco exclude list
-# This appends a * to all classes and replace the space separators with commas.
-# These patterns will match all classes in this module and their inner classes.
-jacoco_exclude := $(subst $(space),$(comma),$(patsubst %,%*,$(local_classes)))
-
-jacoco_include := android.net.wifi.*
-
-LOCAL_JACK_COVERAGE_INCLUDE_FILTER := $(jacoco_include)
-LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- core-test-rules \
- guava \
- mockito-target-minus-junit4 \
- net-tests-utils \
- frameworks-base-testutils \
- truth-prebuilt \
-
-LOCAL_JAVA_LIBRARIES := \
- android.test.runner \
- android.test.base \
-
-LOCAL_PACKAGE_NAME := FrameworksWifiApiTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := \
- device-tests \
- mts \
-
-include $(BUILD_PACKAGE)