Merge "Call setAdapter from handleLayoutChanged." into rvc-dev
diff --git a/Android.bp b/Android.bp
index da5d624..48d9559 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1299,6 +1299,13 @@
"framework-annotations-lib",
"android.hardware.radio-V1.5-java",
],
+ check_api: {
+ current: {
+ // TODO(b/147699819): remove telephony prefix when moved
+ api_file: "telephony/api/system-current.txt",
+ removed_api_file: "telephony/api/system-removed.txt",
+ },
+ },
defaults: ["framework-module-stubs-defaults-systemapi"],
filter_packages: ["android.telephony"],
sdk_version: "system_current",
diff --git a/apex/Android.bp b/apex/Android.bp
index 39137fb..1943940 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -44,6 +44,12 @@
args: mainline_stubs_args,
installable: false,
sdk_version: "current",
+ check_api: {
+ current: {
+ api_file: "api/current.txt",
+ removed_api_file: "api/removed.txt",
+ },
+ },
}
stubs_defaults {
@@ -52,6 +58,12 @@
libs: ["framework-annotations-lib"],
installable: false,
sdk_version: "system_current",
+ check_api: {
+ current: {
+ api_file: "api/system-current.txt",
+ removed_api_file: "api/system-removed.txt",
+ },
+ },
}
// The defaults for module_libs comes in two parts - defaults for API checks
@@ -65,6 +77,12 @@
libs: ["framework-annotations-lib"],
installable: false,
sdk_version: "module_current",
+ check_api: {
+ current: {
+ api_file: "api/module-lib-current.txt",
+ removed_api_file: "api/module-lib-removed.txt",
+ },
+ },
}
stubs_defaults {
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index ae8976a..9f98f8e 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -55,6 +55,10 @@
* using the {@link JobInfo.Builder}.
* The goal here is to provide the scheduler with high-level semantics about the work you want to
* accomplish.
+ * <p> Prior to Android version {@link Build.VERSION_CODES#Q}, you had to specify at least one
+ * constraint on the JobInfo object that you are creating. Otherwise, the builder would throw an
+ * exception when building. From Android version {@link Build.VERSION_CODES#Q} and onwards, it is
+ * valid to schedule jobs with no constraints.
*/
public class JobInfo implements Parcelable {
private static String TAG = "JobInfo";
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 819f253..07a9908 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -746,7 +746,13 @@
final Constants mConstants;
final ConstantsObserver mConstantsObserver;
- static final Comparator<JobStatus> mEnqueueTimeComparator = (o1, o2) -> {
+ private static final Comparator<JobStatus> sPendingJobComparator = (o1, o2) -> {
+ // Jobs with an override state set (via adb) should be put first as tests/developers
+ // expect the jobs to run immediately.
+ if (o1.overrideState != o2.overrideState) {
+ // Higher override state (OVERRIDE_FULL) should be before lower state (OVERRIDE_SOFT)
+ return o2.overrideState - o1.overrideState;
+ }
if (o1.enqueueTime < o2.enqueueTime) {
return -1;
}
@@ -1097,7 +1103,7 @@
// This is a new job, we can just immediately put it on the pending
// list and try to run it.
mJobPackageTracker.notePending(jobStatus);
- addOrderedItem(mPendingJobs, jobStatus, mEnqueueTimeComparator);
+ addOrderedItem(mPendingJobs, jobStatus, sPendingJobComparator);
maybeRunPendingJobsLocked();
} else {
evaluateControllerStatesLocked(jobStatus);
@@ -1858,7 +1864,7 @@
// state is such that all ready jobs should be run immediately.
if (runNow != null && isReadyToBeExecutedLocked(runNow)) {
mJobPackageTracker.notePending(runNow);
- addOrderedItem(mPendingJobs, runNow, mEnqueueTimeComparator);
+ addOrderedItem(mPendingJobs, runNow, sPendingJobComparator);
} else {
queueReadyJobsForExecutionLocked();
}
@@ -2030,7 +2036,7 @@
noteJobsPending(newReadyJobs);
mPendingJobs.addAll(newReadyJobs);
if (mPendingJobs.size() > 1) {
- mPendingJobs.sort(mEnqueueTimeComparator);
+ mPendingJobs.sort(sPendingJobComparator);
}
newReadyJobs.clear();
@@ -2107,7 +2113,7 @@
noteJobsPending(runnableJobs);
mPendingJobs.addAll(runnableJobs);
if (mPendingJobs.size() > 1) {
- mPendingJobs.sort(mEnqueueTimeComparator);
+ mPendingJobs.sort(sPendingJobComparator);
}
} else {
if (DEBUG) {
@@ -2813,11 +2819,9 @@
}
// Shell command infrastructure: run the given job immediately
- int executeRunCommand(String pkgName, int userId, int jobId, boolean force) {
- if (DEBUG) {
- Slog.v(TAG, "executeRunCommand(): " + pkgName + "/" + userId
- + " " + jobId + " f=" + force);
- }
+ int executeRunCommand(String pkgName, int userId, int jobId, boolean satisfied, boolean force) {
+ Slog.d(TAG, "executeRunCommand(): " + pkgName + "/" + userId
+ + " " + jobId + " s=" + satisfied + " f=" + force);
try {
final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0,
@@ -2832,7 +2836,8 @@
return JobSchedulerShellCommand.CMD_ERR_NO_JOB;
}
- js.overrideState = (force) ? JobStatus.OVERRIDE_FULL : JobStatus.OVERRIDE_SOFT;
+ js.overrideState = (force) ? JobStatus.OVERRIDE_FULL
+ : (satisfied ? JobStatus.OVERRIDE_SORTING : JobStatus.OVERRIDE_SOFT);
// Re-evaluate constraints after the override is set in case one of the overridden
// constraints was preventing another constraint from thinking it needed to update.
@@ -2841,7 +2846,7 @@
}
if (!js.isConstraintsSatisfied()) {
- js.overrideState = 0;
+ js.overrideState = JobStatus.OVERRIDE_NONE;
return JobSchedulerShellCommand.CMD_ERR_CONSTRAINTS;
}
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 9571708..1e72062 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -136,6 +136,7 @@
checkPermission("force scheduled jobs");
boolean force = false;
+ boolean satisfied = false;
int userId = UserHandle.USER_SYSTEM;
String opt;
@@ -146,6 +147,11 @@
force = true;
break;
+ case "-s":
+ case "--satisfied":
+ satisfied = true;
+ break;
+
case "-u":
case "--user":
userId = Integer.parseInt(getNextArgRequired());
@@ -157,12 +163,17 @@
}
}
+ if (force && satisfied) {
+ pw.println("Cannot specify both --force and --satisfied");
+ return -1;
+ }
+
final String pkgName = getNextArgRequired();
final int jobId = Integer.parseInt(getNextArgRequired());
final long ident = Binder.clearCallingIdentity();
try {
- int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force);
+ int ret = mInternal.executeRunCommand(pkgName, userId, jobId, satisfied, force);
if (printError(ret, pkgName, userId, jobId)) {
return ret;
}
@@ -424,11 +435,18 @@
pw.println("Job scheduler (jobscheduler) commands:");
pw.println(" help");
pw.println(" Print this help text.");
- pw.println(" run [-f | --force] [-u | --user USER_ID] PACKAGE JOB_ID");
- pw.println(" Trigger immediate execution of a specific scheduled job.");
+ pw.println(" run [-f | --force] [-s | --satisfied] [-u | --user USER_ID] PACKAGE JOB_ID");
+ pw.println(" Trigger immediate execution of a specific scheduled job. For historical");
+ pw.println(" reasons, some constraints, such as battery, are ignored when this");
+ pw.println(" command is called. If you don't want any constraints to be ignored,");
+ pw.println(" include the -s flag.");
pw.println(" Options:");
pw.println(" -f or --force: run the job even if technical constraints such as");
- pw.println(" connectivity are not currently met");
+ pw.println(" connectivity are not currently met. This is incompatible with -f ");
+ pw.println(" and so an error will be reported if both are given.");
+ pw.println(" -s or --satisfied: run the job only if all constraints are met.");
+ pw.println(" This is incompatible with -f and so an error will be reported");
+ pw.println(" if both are given.");
pw.println(" -u or --user: specify which user's job is to be run; the default is");
pw.println(" the primary or system user");
pw.println(" timeout [-u | --user USER_ID] [PACKAGE] [JOB_ID]");
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index 81dbc87..d7c6ddb 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -131,10 +131,14 @@
// TODO(b/129954980)
private static final boolean STATS_LOG_ENABLED = false;
+ // No override.
+ public static final int OVERRIDE_NONE = 0;
+ // Override to improve sorting order. Does not affect constraint evaluation.
+ public static final int OVERRIDE_SORTING = 1;
// Soft override: ignore constraints like time that don't affect API availability
- public static final int OVERRIDE_SOFT = 1;
+ public static final int OVERRIDE_SOFT = 2;
// Full override: ignore all constraints including API-affecting like connectivity
- public static final int OVERRIDE_FULL = 2;
+ public static final int OVERRIDE_FULL = 3;
/** If not specified, trigger update delay is 10 seconds. */
public static final long DEFAULT_TRIGGER_UPDATE_DELAY = 10*1000;
@@ -304,7 +308,7 @@
public int nextPendingWorkId = 1;
// Used by shell commands
- public int overrideState = 0;
+ public int overrideState = JobStatus.OVERRIDE_NONE;
// When this job was enqueued, for ordering. (in elapsedRealtimeMillis)
public long enqueueTime;
diff --git a/apex/media/OWNERS b/apex/media/OWNERS
index 0ac750c..9b853c5 100644
--- a/apex/media/OWNERS
+++ b/apex/media/OWNERS
@@ -1,4 +1,4 @@
andrewlewis@google.com
-dwkang@google.com
+aquilescanta@google.com
marcone@google.com
sungsoo@google.com
diff --git a/apex/media/framework/api/current.txt b/apex/media/framework/api/current.txt
new file mode 100644
index 0000000..2b7dcd33
--- /dev/null
+++ b/apex/media/framework/api/current.txt
@@ -0,0 +1,206 @@
+// Signature format: 2.0
+package android.media {
+
+ public class MediaController2 implements java.lang.AutoCloseable {
+ method public void cancelSessionCommand(@NonNull Object);
+ method public void close();
+ method @Nullable public android.media.Session2Token getConnectedToken();
+ method public boolean isPlaybackActive();
+ method @NonNull public Object sendSessionCommand(@NonNull android.media.Session2Command, @Nullable android.os.Bundle);
+ }
+
+ public static final class MediaController2.Builder {
+ ctor public MediaController2.Builder(@NonNull android.content.Context, @NonNull android.media.Session2Token);
+ method @NonNull public android.media.MediaController2 build();
+ method @NonNull public android.media.MediaController2.Builder setConnectionHints(@NonNull android.os.Bundle);
+ method @NonNull public android.media.MediaController2.Builder setControllerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaController2.ControllerCallback);
+ }
+
+ public abstract static class MediaController2.ControllerCallback {
+ ctor public MediaController2.ControllerCallback();
+ method public void onCommandResult(@NonNull android.media.MediaController2, @NonNull Object, @NonNull android.media.Session2Command, @NonNull android.media.Session2Command.Result);
+ method public void onConnected(@NonNull android.media.MediaController2, @NonNull android.media.Session2CommandGroup);
+ method public void onDisconnected(@NonNull android.media.MediaController2);
+ method public void onPlaybackActiveChanged(@NonNull android.media.MediaController2, boolean);
+ method @Nullable public android.media.Session2Command.Result onSessionCommand(@NonNull android.media.MediaController2, @NonNull android.media.Session2Command, @Nullable android.os.Bundle);
+ }
+
+ public final class MediaParser {
+ method public boolean advance(@NonNull android.media.MediaParser.SeekableInputReader) throws java.io.IOException;
+ method @NonNull public static android.media.MediaParser create(@NonNull android.media.MediaParser.OutputConsumer, @NonNull java.lang.String...);
+ method @NonNull public static android.media.MediaParser createByName(@NonNull String, @NonNull android.media.MediaParser.OutputConsumer);
+ method @Nullable public String getParserName();
+ method @NonNull public static java.util.List<java.lang.String> getParserNames(@NonNull android.media.MediaFormat);
+ method public void release();
+ method public void seek(@NonNull android.media.MediaParser.SeekPoint);
+ method @NonNull public android.media.MediaParser setParameter(@NonNull String, @NonNull Object);
+ method public boolean supportsParameter(@NonNull String);
+ field public static final String PARAMETER_ADTS_ENABLE_CBR_SEEKING = "android.media.mediaparser.adts.enableCbrSeeking";
+ field public static final String PARAMETER_AMR_ENABLE_CBR_SEEKING = "android.media.mediaparser.amr.enableCbrSeeking";
+ field public static final String PARAMETER_FLAC_DISABLE_ID3 = "android.media.mediaparser.flac.disableId3";
+ field public static final String PARAMETER_MATROSKA_DISABLE_CUES_SEEKING = "android.media.mediaparser.matroska.disableCuesSeeking";
+ field public static final String PARAMETER_MP3_DISABLE_ID3 = "android.media.mediaparser.mp3.disableId3";
+ field public static final String PARAMETER_MP3_ENABLE_CBR_SEEKING = "android.media.mediaparser.mp3.enableCbrSeeking";
+ field public static final String PARAMETER_MP3_ENABLE_INDEX_SEEKING = "android.media.mediaparser.mp3.enableIndexSeeking";
+ field public static final String PARAMETER_MP4_IGNORE_EDIT_LISTS = "android.media.mediaparser.mp4.ignoreEditLists";
+ field public static final String PARAMETER_MP4_IGNORE_TFDT_BOX = "android.media.mediaparser.mp4.ignoreTfdtBox";
+ field public static final String PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES = "android.media.mediaparser.mp4.treatVideoFramesAsKeyframes";
+ field public static final String PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES = "android.media.mediaparser.ts.allowNonIdrAvcKeyframes";
+ field public static final String PARAMETER_TS_DETECT_ACCESS_UNITS = "android.media.mediaparser.ts.ignoreDetectAccessUnits";
+ field public static final String PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS = "android.media.mediaparser.ts.enableHdmvDtsAudioStreams";
+ field public static final String PARAMETER_TS_IGNORE_AAC_STREAM = "android.media.mediaparser.ts.ignoreAacStream";
+ field public static final String PARAMETER_TS_IGNORE_AVC_STREAM = "android.media.mediaparser.ts.ignoreAvcStream";
+ field public static final String PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM = "android.media.mediaparser.ts.ignoreSpliceInfoStream";
+ field public static final String PARAMETER_TS_MODE = "android.media.mediaparser.ts.mode";
+ }
+
+ public static interface MediaParser.InputReader {
+ method public long getLength();
+ method public long getPosition();
+ method public int read(@NonNull byte[], int, int) throws java.io.IOException;
+ }
+
+ public static interface MediaParser.OutputConsumer {
+ method public void onSampleCompleted(int, long, int, int, int, @Nullable android.media.MediaCodec.CryptoInfo);
+ method public void onSampleDataFound(int, @NonNull android.media.MediaParser.InputReader) throws java.io.IOException;
+ method public void onSeekMapFound(@NonNull android.media.MediaParser.SeekMap);
+ method public void onTrackCountFound(int);
+ method public void onTrackDataFound(int, @NonNull android.media.MediaParser.TrackData);
+ }
+
+ public static final class MediaParser.ParsingException extends java.io.IOException {
+ }
+
+ public static final class MediaParser.SeekMap {
+ method public long getDurationMicros();
+ method @NonNull public android.util.Pair<android.media.MediaParser.SeekPoint,android.media.MediaParser.SeekPoint> getSeekPoints(long);
+ method public boolean isSeekable();
+ field public static final int UNKNOWN_DURATION = -2147483648; // 0x80000000
+ }
+
+ public static final class MediaParser.SeekPoint {
+ field @NonNull public static final android.media.MediaParser.SeekPoint START;
+ field public final long position;
+ field public final long timeMicros;
+ }
+
+ public static interface MediaParser.SeekableInputReader extends android.media.MediaParser.InputReader {
+ method public void seekToPosition(long);
+ }
+
+ public static final class MediaParser.TrackData {
+ field @Nullable public final android.media.DrmInitData drmInitData;
+ field @NonNull public final android.media.MediaFormat mediaFormat;
+ }
+
+ public static final class MediaParser.UnrecognizedInputFormatException extends java.io.IOException {
+ }
+
+ public class MediaSession2 implements java.lang.AutoCloseable {
+ method public void broadcastSessionCommand(@NonNull android.media.Session2Command, @Nullable android.os.Bundle);
+ method public void cancelSessionCommand(@NonNull android.media.MediaSession2.ControllerInfo, @NonNull Object);
+ method public void close();
+ method @NonNull public java.util.List<android.media.MediaSession2.ControllerInfo> getConnectedControllers();
+ method @NonNull public String getId();
+ method @NonNull public android.media.Session2Token getToken();
+ method public boolean isPlaybackActive();
+ method @NonNull public Object sendSessionCommand(@NonNull android.media.MediaSession2.ControllerInfo, @NonNull android.media.Session2Command, @Nullable android.os.Bundle);
+ method public void setPlaybackActive(boolean);
+ }
+
+ public static final class MediaSession2.Builder {
+ ctor public MediaSession2.Builder(@NonNull android.content.Context);
+ method @NonNull public android.media.MediaSession2 build();
+ method @NonNull public android.media.MediaSession2.Builder setExtras(@NonNull android.os.Bundle);
+ method @NonNull public android.media.MediaSession2.Builder setId(@NonNull String);
+ method @NonNull public android.media.MediaSession2.Builder setSessionActivity(@Nullable android.app.PendingIntent);
+ method @NonNull public android.media.MediaSession2.Builder setSessionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaSession2.SessionCallback);
+ }
+
+ public static final class MediaSession2.ControllerInfo {
+ method @NonNull public android.os.Bundle getConnectionHints();
+ method @NonNull public String getPackageName();
+ method @NonNull public android.media.session.MediaSessionManager.RemoteUserInfo getRemoteUserInfo();
+ method public int getUid();
+ }
+
+ public abstract static class MediaSession2.SessionCallback {
+ ctor public MediaSession2.SessionCallback();
+ method public void onCommandResult(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo, @NonNull Object, @NonNull android.media.Session2Command, @NonNull android.media.Session2Command.Result);
+ method @Nullable public android.media.Session2CommandGroup onConnect(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo);
+ method public void onDisconnected(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo);
+ method public void onPostConnect(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo);
+ method @Nullable public android.media.Session2Command.Result onSessionCommand(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo, @NonNull android.media.Session2Command, @Nullable android.os.Bundle);
+ }
+
+ public abstract class MediaSession2Service extends android.app.Service {
+ ctor public MediaSession2Service();
+ method public final void addSession(@NonNull android.media.MediaSession2);
+ method @NonNull public final java.util.List<android.media.MediaSession2> getSessions();
+ method @CallSuper @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
+ method @Nullable public abstract android.media.MediaSession2 onGetSession(@NonNull android.media.MediaSession2.ControllerInfo);
+ method @Nullable public abstract android.media.MediaSession2Service.MediaNotification onUpdateNotification(@NonNull android.media.MediaSession2);
+ method public final void removeSession(@NonNull android.media.MediaSession2);
+ field public static final String SERVICE_INTERFACE = "android.media.MediaSession2Service";
+ }
+
+ public static class MediaSession2Service.MediaNotification {
+ ctor public MediaSession2Service.MediaNotification(int, @NonNull android.app.Notification);
+ method @NonNull public android.app.Notification getNotification();
+ method public int getNotificationId();
+ }
+
+ public final class Session2Command implements android.os.Parcelable {
+ ctor public Session2Command(int);
+ ctor public Session2Command(@NonNull String, @Nullable android.os.Bundle);
+ method public int describeContents();
+ method public int getCommandCode();
+ method @Nullable public String getCustomAction();
+ method @Nullable public android.os.Bundle getCustomExtras();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.Session2Command> CREATOR;
+ }
+
+ public static final class Session2Command.Result {
+ ctor public Session2Command.Result(int, @Nullable android.os.Bundle);
+ method public int getResultCode();
+ method @Nullable public android.os.Bundle getResultData();
+ field public static final int RESULT_ERROR_UNKNOWN_ERROR = -1; // 0xffffffff
+ field public static final int RESULT_INFO_SKIPPED = 1; // 0x1
+ field public static final int RESULT_SUCCESS = 0; // 0x0
+ }
+
+ public final class Session2CommandGroup implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.Set<android.media.Session2Command> getCommands();
+ method public boolean hasCommand(@NonNull android.media.Session2Command);
+ method public boolean hasCommand(int);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.Session2CommandGroup> CREATOR;
+ }
+
+ public static final class Session2CommandGroup.Builder {
+ ctor public Session2CommandGroup.Builder();
+ ctor public Session2CommandGroup.Builder(@NonNull android.media.Session2CommandGroup);
+ method @NonNull public android.media.Session2CommandGroup.Builder addCommand(@NonNull android.media.Session2Command);
+ method @NonNull public android.media.Session2CommandGroup build();
+ method @NonNull public android.media.Session2CommandGroup.Builder removeCommand(@NonNull android.media.Session2Command);
+ }
+
+ public final class Session2Token implements android.os.Parcelable {
+ ctor public Session2Token(@NonNull android.content.Context, @NonNull android.content.ComponentName);
+ method public int describeContents();
+ method @NonNull public android.os.Bundle getExtras();
+ method @NonNull public String getPackageName();
+ method @Nullable public String getServiceName();
+ method public int getType();
+ method public int getUid();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.Session2Token> CREATOR;
+ field public static final int TYPE_SESSION = 0; // 0x0
+ field public static final int TYPE_SESSION_SERVICE = 1; // 0x1
+ }
+
+}
+
diff --git a/apex/media/framework/api/module-lib-current.txt b/apex/media/framework/api/module-lib-current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/media/framework/api/module-lib-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/media/framework/api/module-lib-removed.txt b/apex/media/framework/api/module-lib-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/media/framework/api/module-lib-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/media/framework/api/removed.txt b/apex/media/framework/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/media/framework/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/media/framework/api/system-current.txt b/apex/media/framework/api/system-current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/media/framework/api/system-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/media/framework/api/system-removed.txt b/apex/media/framework/api/system-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/media/framework/api/system-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index 29c48ad..bb3f4e99 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -25,6 +25,7 @@
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
+import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput;
@@ -103,12 +104,12 @@
* private int bytesWrittenCount = 0;
*
* @Override
- * public void onSeekMap(int i, @NonNull MediaFormat mediaFormat) {
+ * public void onSeekMapFound(int i, @NonNull MediaFormat mediaFormat) {
* // Do nothing.
* }
*
* @Override
- * public void onTrackData(int i, @NonNull TrackData trackData) {
+ * public void onTrackDataFound(int i, @NonNull TrackData trackData) {
* MediaFormat mediaFormat = trackData.mediaFormat;
* if (videoTrackIndex == -1 &&
* mediaFormat
@@ -119,7 +120,7 @@
* }
*
* @Override
- * public void onSampleData(int trackIndex, @NonNull InputReader inputReader)
+ * public void onSampleDataFound(int trackIndex, @NonNull InputReader inputReader)
* throws IOException {
* int numberOfBytesToRead = (int) inputReader.getLength();
* if (videoTrackIndex != trackIndex) {
@@ -386,9 +387,9 @@
* @param flags Flags associated with the sample. See {@link MediaCodec
* MediaCodec.BUFFER_FLAG_*}.
* @param size The size of the sample data, in bytes.
- * @param offset The number of bytes that have been consumed by {@code onSampleData(int,
- * MediaParser.InputReader)} for the specified track, since the last byte belonging to
- * the sample whose metadata is being passed.
+ * @param offset The number of bytes that have been consumed by {@code
+ * onSampleDataFound(int, MediaParser.InputReader)} for the specified track, since the
+ * last byte belonging to the sample whose metadata is being passed.
* @param cryptoData Encryption data required to decrypt the sample. May be null for
* unencrypted samples.
*/
@@ -431,63 +432,75 @@
}
}
+ /** Thrown when an error occurs while parsing a media stream. */
+ public static final class ParsingException extends IOException {
+
+ private ParsingException(ParserException cause) {
+ super(cause);
+ }
+ }
+
// Public constants.
/**
- * Sets whether constant bitrate seeking should be enabled for exo.AdtsParser. {@code boolean}
+ * Sets whether constant bitrate seeking should be enabled for ADTS parsing. {@code boolean}
* expected. Default value is {@code false}.
*/
public static final String PARAMETER_ADTS_ENABLE_CBR_SEEKING =
- "exo.AdtsParser.enableCbrSeeking";
+ "android.media.mediaparser.adts.enableCbrSeeking";
/**
- * Sets whether constant bitrate seeking should be enabled for exo.AmrParser. {@code boolean}
+ * Sets whether constant bitrate seeking should be enabled for AMR. {@code boolean} expected.
+ * Default value is {@code false}.
+ */
+ public static final String PARAMETER_AMR_ENABLE_CBR_SEEKING =
+ "android.media.mediaparser.amr.enableCbrSeeking";
+ /**
+ * Sets whether the ID3 track should be disabled for FLAC. {@code boolean} expected. Default
+ * value is {@code false}.
+ */
+ public static final String PARAMETER_FLAC_DISABLE_ID3 =
+ "android.media.mediaparser.flac.disableId3";
+ /**
+ * Sets whether MP4 parsing should ignore edit lists. {@code boolean} expected. Default value is
+ * {@code false}.
+ */
+ public static final String PARAMETER_MP4_IGNORE_EDIT_LISTS =
+ "android.media.mediaparser.mp4.ignoreEditLists";
+ /**
+ * Sets whether MP4 parsing should ignore the tfdt box. {@code boolean} expected. Default value
+ * is {@code false}.
+ */
+ public static final String PARAMETER_MP4_IGNORE_TFDT_BOX =
+ "android.media.mediaparser.mp4.ignoreTfdtBox";
+ /**
+ * Sets whether MP4 parsing should treat all video frames as key frames. {@code boolean}
* expected. Default value is {@code false}.
*/
- public static final String PARAMETER_AMR_ENABLE_CBR_SEEKING = "exo.AmrParser.enableCbrSeeking";
+ public static final String PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES =
+ "android.media.mediaparser.mp4.treatVideoFramesAsKeyframes";
/**
- * Sets whether the ID3 track should be disabled for exo.FlacParser. {@code boolean} expected.
- * Default value is {@code false}.
- */
- public static final String PARAMETER_FLAC_DISABLE_ID3 = "exo.FlacParser.disableId3";
- /**
- * Sets whether exo.FragmentedMp4Parser should ignore edit lists. {@code boolean} expected.
- * Default value is {@code false}.
- */
- public static final String PARAMETER_FMP4_IGNORE_EDIT_LISTS =
- "exo.FragmentedMp4Parser.ignoreEditLists";
- /**
- * Sets whether exo.FragmentedMp4Parser should ignore the tfdt box. {@code boolean} expected.
- * Default value is {@code false}.
- */
- public static final String PARAMETER_FMP4_IGNORE_TFDT_BOX =
- "exo.FragmentedMp4Parser.ignoreTfdtBox";
- /**
- * Sets whether exo.FragmentedMp4Parser should treat all video frames as key frames. {@code
- * boolean} expected. Default value is {@code false}.
- */
- public static final String PARAMETER_FMP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES =
- "exo.FragmentedMp4Parser.treatVideoFramesAsKeyframes";
- /**
- * Sets whether exo.MatroskaParser should avoid seeking to the cues element. {@code boolean}
+ * Sets whether Matroska parsing should avoid seeking to the cues element. {@code boolean}
* expected. Default value is {@code false}.
*
* <p>If this flag is enabled and the cues element occurs after the first cluster, then the
* media is treated as unseekable.
*/
public static final String PARAMETER_MATROSKA_DISABLE_CUES_SEEKING =
- "exo.MatroskaParser.disableCuesSeeking";
+ "android.media.mediaparser.matroska.disableCuesSeeking";
/**
- * Sets whether the ID3 track should be disabled for exo.Mp3Parser. {@code boolean} expected.
+ * Sets whether the ID3 track should be disabled for MP3. {@code boolean} expected. Default
+ * value is {@code false}.
+ */
+ public static final String PARAMETER_MP3_DISABLE_ID3 =
+ "android.media.mediaparser.mp3.disableId3";
+ /**
+ * Sets whether constant bitrate seeking should be enabled for MP3. {@code boolean} expected.
* Default value is {@code false}.
*/
- public static final String PARAMETER_MP3_DISABLE_ID3 = "exo.Mp3Parser.disableId3";
+ public static final String PARAMETER_MP3_ENABLE_CBR_SEEKING =
+ "android.media.mediaparser.mp3.enableCbrSeeking";
/**
- * Sets whether constant bitrate seeking should be enabled for exo.Mp3Parser. {@code boolean}
- * expected. Default value is {@code false}.
- */
- public static final String PARAMETER_MP3_ENABLE_CBR_SEEKING = "exo.Mp3Parser.enableCbrSeeking";
- /**
- * Sets whether exo.Mp3Parser should generate a time-to-byte mapping. {@code boolean} expected.
+ * Sets whether MP3 parsing should generate a time-to-byte mapping. {@code boolean} expected.
* Default value is {@code false}.
*
* <p>Enabling this flag may require to scan a significant portion of the file to compute a seek
@@ -500,18 +513,13 @@
* </ul>
*/
public static final String PARAMETER_MP3_ENABLE_INDEX_SEEKING =
- "exo.Mp3Parser.enableIndexSeeking";
+ "android.media.mediaparser.mp3.enableIndexSeeking";
/**
- * Sets whether exo.Mp4Parser should ignore edit lists. {@code boolean} expected. Default value
- * is {@code false}.
- */
- public static final String PARAMETER_MP4_IGNORE_EDIT_LISTS = "exo.Mp4Parser.ignoreEditLists";
- /**
- * Sets the operation mode for exo.TsParser. {@code String} expected. Valid values are {@code
+ * Sets the operation mode for TS parsing. {@code String} expected. Valid values are {@code
* "single_pmt"}, {@code "multi_pmt"}, and {@code "hls"}. Default value is {@code "single_pmt"}.
*
- * <p>The operation modes alter the way exo.TsParser behaves so that it can handle certain kinds
- * of commonly-occurring malformed media.
+ * <p>The operation modes alter the way TS behaves so that it can handle certain kinds of
+ * commonly-occurring malformed media.
*
* <ul>
* <li>{@code "single_pmt"}: Only the first found PMT is parsed. Others are ignored, even if
@@ -520,47 +528,48 @@
* <li>{@code "hls"}: Enable {@code "single_pmt"} mode, and ignore continuity counters.
* </ul>
*/
- public static final String PARAMETER_TS_MODE = "exo.TsParser.mode";
+ public static final String PARAMETER_TS_MODE = "android.media.mediaparser.ts.mode";
/**
- * Sets whether exo.TsParser should treat samples consisting of non-IDR I slices as
- * synchronization samples (key-frames). {@code boolean} expected. Default value is {@code
- * false}.
+ * Sets whether TS should treat samples consisting of non-IDR I slices as synchronization
+ * samples (key-frames). {@code boolean} expected. Default value is {@code false}.
*/
public static final String PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES =
- "exo.TsParser.allowNonIdrAvcKeyframes";
+ "android.media.mediaparser.ts.allowNonIdrAvcKeyframes";
/**
- * Sets whether exo.TsParser should ignore AAC elementary streams. {@code boolean} expected.
+ * Sets whether TS parsing should ignore AAC elementary streams. {@code boolean} expected.
* Default value is {@code false}.
*/
- public static final String PARAMETER_TS_IGNORE_AAC_STREAM = "exo.TsParser.ignoreAacStream";
+ public static final String PARAMETER_TS_IGNORE_AAC_STREAM =
+ "android.media.mediaparser.ts.ignoreAacStream";
/**
- * Sets whether exo.TsParser should ignore AVC elementary streams. {@code boolean} expected.
+ * Sets whether TS parsing should ignore AVC elementary streams. {@code boolean} expected.
* Default value is {@code false}.
*/
- public static final String PARAMETER_TS_IGNORE_AVC_STREAM = "exo.TsParser.ignoreAvcStream";
+ public static final String PARAMETER_TS_IGNORE_AVC_STREAM =
+ "android.media.mediaparser.ts.ignoreAvcStream";
/**
- * Sets whether exo.TsParser should ignore splice information streams. {@code boolean} expected.
+ * Sets whether TS parsing should ignore splice information streams. {@code boolean} expected.
* Default value is {@code false}.
*/
public static final String PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM =
- "exo.TsParser.ignoreSpliceInfoStream";
+ "android.media.mediaparser.ts.ignoreSpliceInfoStream";
/**
- * Sets whether exo.TsParser should split AVC stream into access units based on slice headers.
+ * Sets whether TS parsing should split AVC stream into access units based on slice headers.
* {@code boolean} expected. Default value is {@code false}.
*
* <p>This flag should be left disabled if the stream contains access units delimiters in order
* to avoid unnecessary computational costs.
*/
public static final String PARAMETER_TS_DETECT_ACCESS_UNITS =
- "exo.TsParser.ignoreDetectAccessUnits";
+ "android.media.mediaparser.ts.ignoreDetectAccessUnits";
/**
- * Sets whether exo.TsParser should handle HDMV DTS audio streams. {@code boolean} expected.
+ * Sets whether TS parsing should handle HDMV DTS audio streams. {@code boolean} expected.
* Default value is {@code false}.
*
* <p>Enabling this flag will disable the detection of SCTE subtitles.
*/
public static final String PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS =
- "exo.TsParser.enableHdmvDtsAudioStreams";
+ "android.media.mediaparser.ts.enableHdmvDtsAudioStreams";
// Private constants.
@@ -768,6 +777,8 @@
int result = 0;
try {
result = mExtractor.read(mExtractorInput, mPositionHolder);
+ } catch (ParserException e) {
+ throw new ParsingException(e);
} catch (InterruptedException e) {
// TODO: Remove this exception replacement once we update the ExoPlayer version.
throw new InterruptedIOException();
@@ -1174,15 +1185,14 @@
expectedTypeByParameterName.put(PARAMETER_ADTS_ENABLE_CBR_SEEKING, Boolean.class);
expectedTypeByParameterName.put(PARAMETER_AMR_ENABLE_CBR_SEEKING, Boolean.class);
expectedTypeByParameterName.put(PARAMETER_FLAC_DISABLE_ID3, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_FMP4_IGNORE_EDIT_LISTS, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_FMP4_IGNORE_TFDT_BOX, Boolean.class);
+ expectedTypeByParameterName.put(PARAMETER_MP4_IGNORE_EDIT_LISTS, Boolean.class);
+ expectedTypeByParameterName.put(PARAMETER_MP4_IGNORE_TFDT_BOX, Boolean.class);
expectedTypeByParameterName.put(
- PARAMETER_FMP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES, Boolean.class);
+ PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES, Boolean.class);
expectedTypeByParameterName.put(PARAMETER_MATROSKA_DISABLE_CUES_SEEKING, Boolean.class);
expectedTypeByParameterName.put(PARAMETER_MP3_DISABLE_ID3, Boolean.class);
expectedTypeByParameterName.put(PARAMETER_MP3_ENABLE_CBR_SEEKING, Boolean.class);
expectedTypeByParameterName.put(PARAMETER_MP3_ENABLE_INDEX_SEEKING, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_MP4_IGNORE_EDIT_LISTS, Boolean.class);
expectedTypeByParameterName.put(PARAMETER_TS_MODE, String.class);
expectedTypeByParameterName.put(PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES, Boolean.class);
expectedTypeByParameterName.put(PARAMETER_TS_IGNORE_AAC_STREAM, Boolean.class);
diff --git a/apex/permission/framework/api/current.txt b/apex/permission/framework/api/current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/permission/framework/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/permission/framework/api/module-lib-current.txt b/apex/permission/framework/api/module-lib-current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/permission/framework/api/module-lib-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/permission/framework/api/module-lib-removed.txt b/apex/permission/framework/api/module-lib-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/permission/framework/api/module-lib-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/permission/framework/api/removed.txt b/apex/permission/framework/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/permission/framework/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/permission/framework/api/system-current.txt b/apex/permission/framework/api/system-current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/permission/framework/api/system-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/permission/framework/api/system-removed.txt b/apex/permission/framework/api/system-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/permission/framework/api/system-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/sdkextensions/framework/api/current.txt b/apex/sdkextensions/framework/api/current.txt
new file mode 100644
index 0000000..9041262
--- /dev/null
+++ b/apex/sdkextensions/framework/api/current.txt
@@ -0,0 +1,10 @@
+// Signature format: 2.0
+package android.os.ext.test {
+
+ @Deprecated public class Test {
+ ctor @Deprecated public Test();
+ method @Deprecated public void testE();
+ }
+
+}
+
diff --git a/apex/sdkextensions/framework/api/module-lib-current.txt b/apex/sdkextensions/framework/api/module-lib-current.txt
new file mode 100644
index 0000000..494c12f
--- /dev/null
+++ b/apex/sdkextensions/framework/api/module-lib-current.txt
@@ -0,0 +1,9 @@
+// Signature format: 2.0
+package android.os.ext.test {
+
+ @Deprecated public class Test {
+ method @Deprecated public void testD();
+ }
+
+}
+
diff --git a/apex/sdkextensions/framework/api/module-lib-removed.txt b/apex/sdkextensions/framework/api/module-lib-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/sdkextensions/framework/api/module-lib-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/sdkextensions/framework/api/removed.txt b/apex/sdkextensions/framework/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/sdkextensions/framework/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/sdkextensions/framework/api/system-current.txt b/apex/sdkextensions/framework/api/system-current.txt
new file mode 100644
index 0000000..056eb41
--- /dev/null
+++ b/apex/sdkextensions/framework/api/system-current.txt
@@ -0,0 +1,18 @@
+// Signature format: 2.0
+package android.os.ext {
+
+ public class SdkExtensions {
+ method public static int getExtensionVersion(int);
+ }
+
+}
+
+package android.os.ext.test {
+
+ @Deprecated public class Test {
+ method @Deprecated public void testF();
+ method @Deprecated public void testG();
+ }
+
+}
+
diff --git a/apex/sdkextensions/framework/api/system-removed.txt b/apex/sdkextensions/framework/api/system-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/sdkextensions/framework/api/system-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/statsd/framework/api/current.txt b/apex/statsd/framework/api/current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/statsd/framework/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/statsd/framework/api/module-lib-current.txt b/apex/statsd/framework/api/module-lib-current.txt
new file mode 100644
index 0000000..8b6e217
--- /dev/null
+++ b/apex/statsd/framework/api/module-lib-current.txt
@@ -0,0 +1,10 @@
+// Signature format: 2.0
+package android.os {
+
+ public class StatsFrameworkInitializer {
+ method public static void registerServiceWrappers();
+ method public static void setStatsServiceManager(@NonNull android.os.StatsServiceManager);
+ }
+
+}
+
diff --git a/apex/statsd/framework/api/module-lib-removed.txt b/apex/statsd/framework/api/module-lib-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/statsd/framework/api/module-lib-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/statsd/framework/api/removed.txt b/apex/statsd/framework/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/statsd/framework/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/apex/statsd/framework/api/system-current.txt b/apex/statsd/framework/api/system-current.txt
new file mode 100644
index 0000000..3ea5724
--- /dev/null
+++ b/apex/statsd/framework/api/system-current.txt
@@ -0,0 +1,111 @@
+// Signature format: 2.0
+package android.app {
+
+ public final class StatsManager {
+ method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void addConfig(long, byte[]) throws android.app.StatsManager.StatsUnavailableException;
+ method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean addConfiguration(long, byte[]);
+ method @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) public void clearPullAtomCallback(int);
+ method @Deprecated @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getData(long);
+ method @Deprecated @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getMetadata();
+ method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] getRegisteredExperimentIds() throws android.app.StatsManager.StatsUnavailableException;
+ method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getReports(long) throws android.app.StatsManager.StatsUnavailableException;
+ method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getStatsMetadata() throws android.app.StatsManager.StatsUnavailableException;
+ method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void removeConfig(long) throws android.app.StatsManager.StatsUnavailableException;
+ method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean removeConfiguration(long);
+ method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] setActiveConfigsChangedOperation(@Nullable android.app.PendingIntent) throws android.app.StatsManager.StatsUnavailableException;
+ method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setBroadcastSubscriber(android.app.PendingIntent, long, long) throws android.app.StatsManager.StatsUnavailableException;
+ method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setBroadcastSubscriber(long, long, android.app.PendingIntent);
+ method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setDataFetchOperation(long, android.app.PendingIntent);
+ method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setFetchReportsOperation(android.app.PendingIntent, long) throws android.app.StatsManager.StatsUnavailableException;
+ method @RequiresPermission(android.Manifest.permission.REGISTER_STATS_PULL_ATOM) public void setPullAtomCallback(int, @Nullable android.app.StatsManager.PullAtomMetadata, @NonNull java.util.concurrent.Executor, @NonNull android.app.StatsManager.StatsPullAtomCallback);
+ field public static final String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED";
+ field public static final String EXTRA_STATS_ACTIVE_CONFIG_KEYS = "android.app.extra.STATS_ACTIVE_CONFIG_KEYS";
+ field public static final String EXTRA_STATS_BROADCAST_SUBSCRIBER_COOKIES = "android.app.extra.STATS_BROADCAST_SUBSCRIBER_COOKIES";
+ field public static final String EXTRA_STATS_CONFIG_KEY = "android.app.extra.STATS_CONFIG_KEY";
+ field public static final String EXTRA_STATS_CONFIG_UID = "android.app.extra.STATS_CONFIG_UID";
+ field public static final String EXTRA_STATS_DIMENSIONS_VALUE = "android.app.extra.STATS_DIMENSIONS_VALUE";
+ field public static final String EXTRA_STATS_SUBSCRIPTION_ID = "android.app.extra.STATS_SUBSCRIPTION_ID";
+ field public static final String EXTRA_STATS_SUBSCRIPTION_RULE_ID = "android.app.extra.STATS_SUBSCRIPTION_RULE_ID";
+ field public static final int PULL_SKIP = 1; // 0x1
+ field public static final int PULL_SUCCESS = 0; // 0x0
+ }
+
+ public static class StatsManager.PullAtomMetadata {
+ method @Nullable public int[] getAdditiveFields();
+ method public long getCoolDownMillis();
+ method public long getTimeoutMillis();
+ }
+
+ public static class StatsManager.PullAtomMetadata.Builder {
+ ctor public StatsManager.PullAtomMetadata.Builder();
+ method @NonNull public android.app.StatsManager.PullAtomMetadata build();
+ method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setAdditiveFields(@NonNull int[]);
+ method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setCoolDownMillis(long);
+ method @NonNull public android.app.StatsManager.PullAtomMetadata.Builder setTimeoutMillis(long);
+ }
+
+ public static interface StatsManager.StatsPullAtomCallback {
+ method public int onPullAtom(int, @NonNull java.util.List<android.util.StatsEvent>);
+ }
+
+ public static class StatsManager.StatsUnavailableException extends android.util.AndroidException {
+ ctor public StatsManager.StatsUnavailableException(String);
+ ctor public StatsManager.StatsUnavailableException(String, Throwable);
+ }
+
+}
+
+package android.os {
+
+ public final class StatsDimensionsValue implements android.os.Parcelable {
+ method public int describeContents();
+ method public boolean getBooleanValue();
+ method public int getField();
+ method public float getFloatValue();
+ method public int getIntValue();
+ method public long getLongValue();
+ method public String getStringValue();
+ method public java.util.List<android.os.StatsDimensionsValue> getTupleValueList();
+ method public int getValueType();
+ method public boolean isValueType(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int BOOLEAN_VALUE_TYPE = 5; // 0x5
+ field @NonNull public static final android.os.Parcelable.Creator<android.os.StatsDimensionsValue> CREATOR;
+ field public static final int FLOAT_VALUE_TYPE = 6; // 0x6
+ field public static final int INT_VALUE_TYPE = 3; // 0x3
+ field public static final int LONG_VALUE_TYPE = 4; // 0x4
+ field public static final int STRING_VALUE_TYPE = 2; // 0x2
+ field public static final int TUPLE_VALUE_TYPE = 7; // 0x7
+ }
+
+}
+
+package android.util {
+
+ public final class StatsEvent {
+ method @NonNull public static android.util.StatsEvent.Builder newBuilder();
+ }
+
+ public static final class StatsEvent.Builder {
+ method @NonNull public android.util.StatsEvent.Builder addBooleanAnnotation(byte, boolean);
+ method @NonNull public android.util.StatsEvent.Builder addIntAnnotation(byte, int);
+ method @NonNull public android.util.StatsEvent build();
+ method @NonNull public android.util.StatsEvent.Builder setAtomId(int);
+ method @NonNull public android.util.StatsEvent.Builder usePooledBuffer();
+ method @NonNull public android.util.StatsEvent.Builder writeAttributionChain(@NonNull int[], @NonNull String[]);
+ method @NonNull public android.util.StatsEvent.Builder writeBoolean(boolean);
+ method @NonNull public android.util.StatsEvent.Builder writeByteArray(@NonNull byte[]);
+ method @NonNull public android.util.StatsEvent.Builder writeFloat(float);
+ method @NonNull public android.util.StatsEvent.Builder writeInt(int);
+ method @NonNull public android.util.StatsEvent.Builder writeKeyValuePairs(@Nullable android.util.SparseIntArray, @Nullable android.util.SparseLongArray, @Nullable android.util.SparseArray<java.lang.String>, @Nullable android.util.SparseArray<java.lang.Float>);
+ method @NonNull public android.util.StatsEvent.Builder writeLong(long);
+ method @NonNull public android.util.StatsEvent.Builder writeString(@NonNull String);
+ }
+
+ public final class StatsLog {
+ method public static void write(@NonNull android.util.StatsEvent);
+ method public static void writeRaw(@NonNull byte[], int);
+ }
+
+}
+
diff --git a/apex/statsd/framework/api/system-removed.txt b/apex/statsd/framework/api/system-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/apex/statsd/framework/api/system-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/api/current.txt b/api/current.txt
index 5e8158b..baad02c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -288,9 +288,9 @@
field public static final int alignmentMode = 16843642; // 0x101037a
field public static final int allContactsName = 16843468; // 0x10102cc
field public static final int allowAudioPlaybackCapture = 16844289; // 0x1010601
+ field public static final int allowAutoRevokePermissionsExemption = 16844309; // 0x1010615
field public static final int allowBackup = 16843392; // 0x1010280
field public static final int allowClearUserData = 16842757; // 0x1010005
- field public static final int allowDontAutoRevokePermissions = 16844309; // 0x1010615
field public static final int allowEmbedded = 16843765; // 0x10103f5
field public static final int allowNativeHeapPointerTagging = 16844307; // 0x1010613
field public static final int allowParallelSyncs = 16843570; // 0x1010332
@@ -1140,7 +1140,7 @@
field public static final int reqKeyboardType = 16843304; // 0x1010228
field public static final int reqNavigation = 16843306; // 0x101022a
field public static final int reqTouchScreen = 16843303; // 0x1010227
- field public static final int requestDontAutoRevokePermissions = 16844308; // 0x1010614
+ field public static final int requestAutoRevokePermissionsExemption = 16844308; // 0x1010614
field public static final int requestLegacyExternalStorage = 16844291; // 0x1010603
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
@@ -4049,6 +4049,7 @@
method @RequiresPermission(android.Manifest.permission.REORDER_TASKS) public void moveTaskToFront(int, int);
method @RequiresPermission(android.Manifest.permission.REORDER_TASKS) public void moveTaskToFront(int, int, android.os.Bundle);
method @Deprecated public void restartPackage(String);
+ method public void setProcessStateSummary(@Nullable byte[]);
method public static void setVrThread(int);
method public void setWatchHeapLimit(long);
field public static final String ACTION_REPORT_HEAP_LIMIT = "android.app.action.REPORT_HEAP_LIMIT";
@@ -4561,12 +4562,14 @@
method public int getPackageUid();
method public int getPid();
method @NonNull public String getProcessName();
+ method @Nullable public byte[] getProcessStateSummary();
method public long getPss();
method public int getRealUid();
method public int getReason();
method public long getRss();
method public int getStatus();
method public long getTimestamp();
+ method @Nullable public java.io.InputStream getTraceInputStream() throws java.io.IOException;
method @NonNull public android.os.UserHandle getUserHandle();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.ApplicationExitInfo> CREATOR;
@@ -5995,7 +5998,7 @@
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(String);
method public java.util.Map<java.lang.String,android.app.AutomaticZenRule> getAutomaticZenRules();
- method @Nullable public android.app.NotificationManager.Policy getConsolidatedNotificationPolicy();
+ method @NonNull public android.app.NotificationManager.Policy getConsolidatedNotificationPolicy();
method public final int getCurrentInterruptionFilter();
method public int getImportance();
method public android.app.NotificationChannel getNotificationChannel(String);
@@ -6942,7 +6945,7 @@
method public boolean isApplicationHidden(@NonNull android.content.ComponentName, String);
method public boolean isBackupServiceEnabled(@NonNull android.content.ComponentName);
method @Deprecated public boolean isCallerApplicationRestrictionsManagingPackage();
- method public boolean isCommonCriteriaModeEnabled(@NonNull android.content.ComponentName);
+ method public boolean isCommonCriteriaModeEnabled(@Nullable android.content.ComponentName);
method public boolean isDeviceIdAttestationSupported();
method public boolean isDeviceOwnerApp(String);
method public boolean isEphemeralUser(@NonNull android.content.ComponentName);
@@ -10202,7 +10205,6 @@
field public static final String MEDIA_ROUTER_SERVICE = "media_router";
field public static final String MEDIA_SESSION_SERVICE = "media_session";
field public static final String MIDI_SERVICE = "midi";
- field public static final String MMS_SERVICE = "mms";
field public static final int MODE_APPEND = 32768; // 0x8000
field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
field @Deprecated public static final int MODE_MULTI_PROCESS = 4; // 0x4
@@ -11721,6 +11723,7 @@
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(@Nullable android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
+ method @NonNull public android.content.pm.LauncherApps.ShortcutQuery setLocusIds(@Nullable java.util.List<android.content.LocusId>);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(@Nullable String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(@Nullable java.util.List<java.lang.String>);
@@ -23600,13 +23603,13 @@
method @FloatRange(from=0, to=63) public double getCn0DbHz();
method @NonNull public String getCodeType();
method public int getConstellationType();
+ method public double getFullInterSignalBiasNanos();
+ method @FloatRange(from=0.0) public double getFullInterSignalBiasUncertaintyNanos();
method public int getMultipathIndicator();
method public double getPseudorangeRateMetersPerSecond();
method public double getPseudorangeRateUncertaintyMetersPerSecond();
method public long getReceivedSvTimeNanos();
method public long getReceivedSvTimeUncertaintyNanos();
- method public double getReceiverInterSignalBiasNanos();
- method @FloatRange(from=0.0) public double getReceiverInterSignalBiasUncertaintyNanos();
method public double getSatelliteInterSignalBiasNanos();
method @FloatRange(from=0.0) public double getSatelliteInterSignalBiasUncertaintyNanos();
method public double getSnrInDb();
@@ -23620,8 +23623,8 @@
method @Deprecated public boolean hasCarrierPhase();
method @Deprecated public boolean hasCarrierPhaseUncertainty();
method public boolean hasCodeType();
- method public boolean hasReceiverInterSignalBiasNanos();
- method public boolean hasReceiverInterSignalBiasUncertaintyNanos();
+ method public boolean hasFullInterSignalBiasNanos();
+ method public boolean hasFullInterSignalBiasUncertaintyNanos();
method public boolean hasSatelliteInterSignalBiasNanos();
method public boolean hasSatelliteInterSignalBiasUncertaintyNanos();
method public boolean hasSnrInDb();
@@ -26427,24 +26430,23 @@
method public void seek(@NonNull android.media.MediaParser.SeekPoint);
method @NonNull public android.media.MediaParser setParameter(@NonNull String, @NonNull Object);
method public boolean supportsParameter(@NonNull String);
- field public static final String PARAMETER_ADTS_ENABLE_CBR_SEEKING = "exo.AdtsParser.enableCbrSeeking";
- field public static final String PARAMETER_AMR_ENABLE_CBR_SEEKING = "exo.AmrParser.enableCbrSeeking";
- field public static final String PARAMETER_FLAC_DISABLE_ID3 = "exo.FlacParser.disableId3";
- field public static final String PARAMETER_FMP4_IGNORE_EDIT_LISTS = "exo.FragmentedMp4Parser.ignoreEditLists";
- field public static final String PARAMETER_FMP4_IGNORE_TFDT_BOX = "exo.FragmentedMp4Parser.ignoreTfdtBox";
- field public static final String PARAMETER_FMP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES = "exo.FragmentedMp4Parser.treatVideoFramesAsKeyframes";
- field public static final String PARAMETER_MATROSKA_DISABLE_CUES_SEEKING = "exo.MatroskaParser.disableCuesSeeking";
- field public static final String PARAMETER_MP3_DISABLE_ID3 = "exo.Mp3Parser.disableId3";
- field public static final String PARAMETER_MP3_ENABLE_CBR_SEEKING = "exo.Mp3Parser.enableCbrSeeking";
- field public static final String PARAMETER_MP3_ENABLE_INDEX_SEEKING = "exo.Mp3Parser.enableIndexSeeking";
- field public static final String PARAMETER_MP4_IGNORE_EDIT_LISTS = "exo.Mp4Parser.ignoreEditLists";
- field public static final String PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES = "exo.TsParser.allowNonIdrAvcKeyframes";
- field public static final String PARAMETER_TS_DETECT_ACCESS_UNITS = "exo.TsParser.ignoreDetectAccessUnits";
- field public static final String PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS = "exo.TsParser.enableHdmvDtsAudioStreams";
- field public static final String PARAMETER_TS_IGNORE_AAC_STREAM = "exo.TsParser.ignoreAacStream";
- field public static final String PARAMETER_TS_IGNORE_AVC_STREAM = "exo.TsParser.ignoreAvcStream";
- field public static final String PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM = "exo.TsParser.ignoreSpliceInfoStream";
- field public static final String PARAMETER_TS_MODE = "exo.TsParser.mode";
+ field public static final String PARAMETER_ADTS_ENABLE_CBR_SEEKING = "android.media.mediaparser.adts.enableCbrSeeking";
+ field public static final String PARAMETER_AMR_ENABLE_CBR_SEEKING = "android.media.mediaparser.amr.enableCbrSeeking";
+ field public static final String PARAMETER_FLAC_DISABLE_ID3 = "android.media.mediaparser.flac.disableId3";
+ field public static final String PARAMETER_MATROSKA_DISABLE_CUES_SEEKING = "android.media.mediaparser.matroska.disableCuesSeeking";
+ field public static final String PARAMETER_MP3_DISABLE_ID3 = "android.media.mediaparser.mp3.disableId3";
+ field public static final String PARAMETER_MP3_ENABLE_CBR_SEEKING = "android.media.mediaparser.mp3.enableCbrSeeking";
+ field public static final String PARAMETER_MP3_ENABLE_INDEX_SEEKING = "android.media.mediaparser.mp3.enableIndexSeeking";
+ field public static final String PARAMETER_MP4_IGNORE_EDIT_LISTS = "android.media.mediaparser.mp4.ignoreEditLists";
+ field public static final String PARAMETER_MP4_IGNORE_TFDT_BOX = "android.media.mediaparser.mp4.ignoreTfdtBox";
+ field public static final String PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES = "android.media.mediaparser.mp4.treatVideoFramesAsKeyframes";
+ field public static final String PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES = "android.media.mediaparser.ts.allowNonIdrAvcKeyframes";
+ field public static final String PARAMETER_TS_DETECT_ACCESS_UNITS = "android.media.mediaparser.ts.ignoreDetectAccessUnits";
+ field public static final String PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS = "android.media.mediaparser.ts.enableHdmvDtsAudioStreams";
+ field public static final String PARAMETER_TS_IGNORE_AAC_STREAM = "android.media.mediaparser.ts.ignoreAacStream";
+ field public static final String PARAMETER_TS_IGNORE_AVC_STREAM = "android.media.mediaparser.ts.ignoreAvcStream";
+ field public static final String PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM = "android.media.mediaparser.ts.ignoreSpliceInfoStream";
+ field public static final String PARAMETER_TS_MODE = "android.media.mediaparser.ts.mode";
}
public static interface MediaParser.InputReader {
@@ -26461,6 +26463,9 @@
method public void onTrackDataFound(int, @NonNull android.media.MediaParser.TrackData);
}
+ public static final class MediaParser.ParsingException extends java.io.IOException {
+ }
+
public static final class MediaParser.SeekMap {
method public long getDurationMicros();
method @NonNull public android.util.Pair<android.media.MediaParser.SeekPoint,android.media.MediaParser.SeekPoint> getSeekPoints(long);
@@ -29818,7 +29823,7 @@
public abstract static class ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback {
ctor public ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback();
- method public void onConnectivityReport(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityReport);
+ method public void onConnectivityReportAvailable(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityReport);
method public void onDataStallSuspected(@NonNull android.net.ConnectivityDiagnosticsManager.DataStallReport);
method public void onNetworkConnectivityReported(@NonNull android.net.Network, boolean);
}
@@ -32450,7 +32455,7 @@
method public boolean categoryAllowsForegroundPreference(String);
method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public java.util.List<java.lang.String> getAidsForPreferredPaymentService();
method public java.util.List<java.lang.String> getAidsForService(android.content.ComponentName, String);
- method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public String getDescriptionForPreferredPaymentService();
+ method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public CharSequence getDescriptionForPreferredPaymentService();
method public static android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter);
method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public String getRouteDestinationForPreferredPaymentService();
method public int getSelectionModeForCategory(String);
@@ -43118,7 +43123,6 @@
public static final class FillResponse.Builder {
ctor public FillResponse.Builder();
method @NonNull public android.service.autofill.FillResponse.Builder addDataset(@Nullable android.service.autofill.Dataset);
- method @NonNull public android.service.autofill.FillResponse.Builder addInlineAction(@NonNull android.service.autofill.InlineAction);
method @NonNull public android.service.autofill.FillResponse build();
method @NonNull public android.service.autofill.FillResponse.Builder disableAutofill(long);
method @NonNull public android.service.autofill.FillResponse.Builder setAuthentication(@NonNull android.view.autofill.AutofillId[], @Nullable android.content.IntentSender, @Nullable android.widget.RemoteViews);
@@ -43148,15 +43152,6 @@
method public android.service.autofill.ImageTransformation build();
}
- public final class InlineAction implements android.os.Parcelable {
- ctor public InlineAction(@NonNull android.service.autofill.InlinePresentation, @NonNull android.content.IntentSender);
- method public int describeContents();
- method @NonNull public android.content.IntentSender getAction();
- method @NonNull public android.service.autofill.InlinePresentation getInlinePresentation();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.service.autofill.InlineAction> CREATOR;
- }
-
public final class InlinePresentation implements android.os.Parcelable {
ctor public InlinePresentation(@NonNull android.app.slice.Slice, @NonNull android.view.inline.InlinePresentationSpec, boolean);
method public int describeContents();
@@ -47542,11 +47537,6 @@
method @Nullable public android.telephony.mbms.StreamingService startStreaming(android.telephony.mbms.StreamingServiceInfo, @NonNull java.util.concurrent.Executor, android.telephony.mbms.StreamingServiceCallback);
}
- public class MmsManager {
- method public void downloadMultimediaMessage(int, @NonNull String, @NonNull android.net.Uri, @Nullable android.os.Bundle, @Nullable android.app.PendingIntent, long);
- method public void sendMultimediaMessage(int, @NonNull android.net.Uri, @Nullable String, @Nullable android.os.Bundle, @Nullable android.app.PendingIntent, long);
- }
-
@Deprecated public class NeighboringCellInfo implements android.os.Parcelable {
ctor @Deprecated public NeighboringCellInfo();
ctor @Deprecated public NeighboringCellInfo(int, int);
@@ -48107,7 +48097,7 @@
method public long getDataLimitBytes();
method public long getDataUsageBytes();
method public long getDataUsageTime();
- method @Nullable public int[] getNetworkTypes();
+ method @NonNull public int[] getNetworkTypes();
method @Nullable public CharSequence getSummary();
method @Nullable public CharSequence getTitle();
method public void writeToParcel(android.os.Parcel, int);
@@ -48127,7 +48117,7 @@
method public static android.telephony.SubscriptionPlan.Builder createRecurring(java.time.ZonedDateTime, java.time.Period);
method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int);
method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long);
- method @NonNull public android.telephony.SubscriptionPlan.Builder setNetworkTypes(@Nullable int[]);
+ method @NonNull public android.telephony.SubscriptionPlan.Builder setNetworkTypes(@NonNull int[]);
method public android.telephony.SubscriptionPlan.Builder setSummary(@Nullable CharSequence);
method public android.telephony.SubscriptionPlan.Builder setTitle(@Nullable CharSequence);
}
@@ -48210,7 +48200,6 @@
method @Deprecated public String iccTransmitApduBasicChannel(int, int, int, int, int, String);
method @Deprecated public String iccTransmitApduLogicalChannel(int, int, int, int, int, int, String);
method public boolean isConcurrentVoiceAndDataSupported();
- method public boolean isDataCapable();
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean isDataEnabled();
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataRoamingEnabled();
method public boolean isEmergencyNumber(@NonNull String);
@@ -53617,6 +53606,7 @@
public static final class SurfaceControlViewHost.SurfacePackage implements android.os.Parcelable {
method public int describeContents();
+ method public void release();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.view.SurfaceControlViewHost.SurfacePackage> CREATOR;
}
@@ -55570,7 +55560,8 @@
}
public interface WindowInsetsAnimationControlListener {
- method public void onCancelled();
+ method public void onCancelled(@Nullable android.view.WindowInsetsAnimationController);
+ method public void onFinished(@NonNull android.view.WindowInsetsAnimationController);
method public void onReady(@NonNull android.view.WindowInsetsAnimationController, int);
}
@@ -55582,6 +55573,9 @@
method @NonNull public android.graphics.Insets getHiddenStateInsets();
method @NonNull public android.graphics.Insets getShownStateInsets();
method public int getTypes();
+ method public boolean isCancelled();
+ method public boolean isFinished();
+ method public default boolean isReady();
method public void setInsetsAndAlpha(@Nullable android.graphics.Insets, @FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=0.0f, to=1.0f) float);
}
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index ee997f1..cfb9b83 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -72,19 +72,20 @@
field public static final int TETHERING_WIFI = 0; // 0x0
field public static final int TETHERING_WIFI_P2P = 3; // 0x3
field public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; // 0xc
- field public static final int TETHER_ERROR_DISABLE_NAT_ERROR = 9; // 0x9
- field public static final int TETHER_ERROR_ENABLE_NAT_ERROR = 8; // 0x8
+ field public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9; // 0x9
+ field public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8; // 0x8
field public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; // 0xd
field public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; // 0xa
- field public static final int TETHER_ERROR_MASTER_ERROR = 5; // 0x5
+ field public static final int TETHER_ERROR_INTERNAL_ERROR = 5; // 0x5
field public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; // 0xf
field public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; // 0xe
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 TETHER_ERROR_PROVISIONING_FAILED = 11; // 0xb
field public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; // 0x2
field public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; // 0x6
field public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; // 0x4
field public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; // 0x1
+ field public static final int TETHER_ERROR_UNKNOWN_TYPE = 16; // 0x10
field public static final int TETHER_ERROR_UNSUPPORTED = 3; // 0x3
field public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; // 0x7
field public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2; // 0x2
@@ -96,29 +97,26 @@
method public void onTetheringEntitlementResult(int);
}
- public abstract static class TetheringManager.StartTetheringCallback {
- ctor public TetheringManager.StartTetheringCallback();
- method public void onTetheringFailed(int);
- method public void onTetheringStarted();
+ public static interface TetheringManager.StartTetheringCallback {
+ method public default void onTetheringFailed(int);
+ method public default void onTetheringStarted();
}
- public abstract static class TetheringManager.TetheringEventCallback {
- ctor public TetheringManager.TetheringEventCallback();
- method public void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
- method public void onError(@NonNull String, int);
- method public void onOffloadStatusChanged(int);
- method @Deprecated public void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
- method public void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
- method public void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
- method public void onTetheringSupported(boolean);
- method public void onUpstreamChanged(@Nullable android.net.Network);
+ public static interface TetheringManager.TetheringEventCallback {
+ method public default void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
+ method public default void onError(@NonNull String, int);
+ method public default void onOffloadStatusChanged(int);
+ method public default void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
+ method public default void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+ method public default void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+ method public default void onTetheringSupported(boolean);
+ method public default void onUpstreamChanged(@Nullable android.net.Network);
}
- @Deprecated public static class TetheringManager.TetheringInterfaceRegexps {
- ctor @Deprecated public TetheringManager.TetheringInterfaceRegexps(@NonNull String[], @NonNull String[], @NonNull String[]);
- method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs();
- method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs();
- method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
+ public static class TetheringManager.TetheringInterfaceRegexps {
+ method @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs();
+ method @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs();
+ method @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
}
public static class TetheringManager.TetheringRequest {
@@ -127,9 +125,14 @@
public static class TetheringManager.TetheringRequest.Builder {
ctor public TetheringManager.TetheringRequest.Builder(int);
method @NonNull public android.net.TetheringManager.TetheringRequest build();
+ method @Nullable public android.net.LinkAddress getClientStaticIpv4Address();
+ method @Nullable public android.net.LinkAddress getLocalIpv4Address();
+ method public boolean getShouldShowEntitlementUi();
+ method public int getTetheringType();
+ method public boolean isExemptFromEntitlementCheck();
method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean);
- method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setSilentProvisioning(boolean);
- method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder useStaticIpv4Addresses(@NonNull android.net.LinkAddress);
+ method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setShouldShowEntitlementUi(boolean);
+ method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setStaticIpv4Addresses(@NonNull android.net.LinkAddress, @NonNull android.net.LinkAddress);
}
}
diff --git a/api/system-current.txt b/api/system-current.txt
index ab3bcc1..f8cb6c9 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -148,6 +148,7 @@
field public static final String NETWORK_SETUP_WIZARD = "android.permission.NETWORK_SETUP_WIZARD";
field public static final String NETWORK_SIGNAL_STRENGTH_WAKEUP = "android.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP";
field public static final String NETWORK_STACK = "android.permission.NETWORK_STACK";
+ field public static final String NETWORK_STATS_PROVIDER = "android.permission.NETWORK_STATS_PROVIDER";
field public static final String NOTIFICATION_DURING_SETUP = "android.permission.NOTIFICATION_DURING_SETUP";
field public static final String NOTIFY_TV_INPUTS = "android.permission.NOTIFY_TV_INPUTS";
field public static final String OBSERVE_APP_USAGE = "android.permission.OBSERVE_APP_USAGE";
@@ -205,7 +206,7 @@
field public static final String REVIEW_ACCESSIBILITY_SERVICES = "android.permission.REVIEW_ACCESSIBILITY_SERVICES";
field public static final String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
field public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
- field public static final String SECURE_ELEMENT_PRIVILEGED = "android.permission.SECURE_ELEMENT_PRIVILEGED";
+ field public static final String SECURE_ELEMENT_PRIVILEGED_OPERATION = "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION";
field public static final String SEND_DEVICE_CUSTOMIZATION_READY = "android.permission.SEND_DEVICE_CUSTOMIZATION_READY";
field public static final String SEND_SHOW_SUSPENDED_APP_DETAILS = "android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS";
field public static final String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION";
@@ -350,7 +351,6 @@
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 public void unregisterHomeVisibilityObserver(@NonNull android.app.HomeVisibilityObserver);
- method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String);
}
public static interface ActivityManager.OnUidImportanceListener {
@@ -387,6 +387,7 @@
field public static final String OPSTR_AUDIO_NOTIFICATION_VOLUME = "android:audio_notification_volume";
field public static final String OPSTR_AUDIO_RING_VOLUME = "android:audio_ring_volume";
field public static final String OPSTR_AUDIO_VOICE_VOLUME = "android:audio_voice_volume";
+ field public static final String OPSTR_AUTO_REVOKE_MANAGED_BY_INSTALLER = "android:auto_revoke_managed_by_installer";
field public static final String OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = "android:auto_revoke_permissions_if_unused";
field public static final String OPSTR_BIND_ACCESSIBILITY_SERVICE = "android:bind_accessibility_service";
field public static final String OPSTR_CHANGE_WIFI_STATE = "android:change_wifi_state";
@@ -1410,7 +1411,8 @@
}
public class NetworkStatsManager {
- method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.net.netstats.provider.NetworkStatsProviderCallback registerNetworkStatsProvider(@NonNull String, @NonNull android.net.netstats.provider.AbstractNetworkStatsProvider);
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void registerNetworkStatsProvider(@NonNull String, @NonNull android.net.netstats.provider.NetworkStatsProvider);
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void unregisterNetworkStatsProvider(@NonNull android.net.netstats.provider.NetworkStatsProvider);
}
public static final class UsageEvents.Event {
@@ -1805,7 +1807,6 @@
field public static final String NETD_SERVICE = "netd";
field public static final String NETWORK_POLICY_SERVICE = "netpolicy";
field public static final String NETWORK_SCORE_SERVICE = "network_score";
- field public static final String NETWORK_STACK_SERVICE = "network_stack";
field public static final String OEM_LOCK_SERVICE = "oem_lock";
field public static final String PERMISSION_SERVICE = "permission";
field public static final String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
@@ -1869,7 +1870,6 @@
field public static final String ACTION_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
field public static final String ACTION_USER_ADDED = "android.intent.action.USER_ADDED";
field public static final String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED";
- field @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public static final String ACTION_USER_SWITCHED = "android.intent.action.USER_SWITCHED";
field public static final String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
field public static final String CATEGORY_LEANBACK_SETTINGS = "android.intent.category.LEANBACK_SETTINGS";
field public static final String EXTRA_CALLING_PACKAGE = "android.intent.extra.CALLING_PACKAGE";
@@ -2102,10 +2102,6 @@
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.LauncherApps.AppUsageLimit> CREATOR;
}
- public static class LauncherApps.ShortcutQuery {
- method @NonNull public android.content.pm.LauncherApps.ShortcutQuery setLocusIds(@Nullable java.util.List<android.content.LocusId>);
- }
-
public class PackageInstaller {
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setPermissionsResult(int, boolean);
field public static final int DATA_LOADER_TYPE_INCREMENTAL = 2; // 0x2
@@ -2316,7 +2312,6 @@
field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
field public static final int PROTECTION_FLAG_RETAIL_DEMO = 16777216; // 0x1000000
field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
- field public static final int PROTECTION_FLAG_TELEPHONY = 4194304; // 0x400000
field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000
field @Nullable public final String backgroundPermission;
field @StringRes public int requestRes;
@@ -4831,11 +4826,11 @@
}
public class Lnb implements java.lang.AutoCloseable {
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void close();
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int sendDiseqcMessage(@NonNull byte[]);
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int setSatellitePosition(int);
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int setTone(int);
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int setVoltage(int);
+ method public void close();
+ method public int sendDiseqcMessage(@NonNull byte[]);
+ method public int setSatellitePosition(int);
+ method public int setTone(int);
+ method public int setVoltage(int);
field public static final int EVENT_TYPE_DISEQC_RX_OVERFLOW = 0; // 0x0
field public static final int EVENT_TYPE_DISEQC_RX_PARITY_ERROR = 2; // 0x2
field public static final int EVENT_TYPE_DISEQC_RX_TIMEOUT = 1; // 0x1
@@ -4863,42 +4858,36 @@
public class Tuner implements java.lang.AutoCloseable {
ctor @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public Tuner(@NonNull android.content.Context, @Nullable String, int);
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int cancelScanning();
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int cancelTuning();
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void clearOnTuneEventListener();
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void clearResourceLostListener();
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void close();
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int connectCiCam(int);
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int disconnectCiCam();
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int getAvSyncHwId(@NonNull android.media.tv.tuner.filter.Filter);
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public long getAvSyncTime(int);
- method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public static android.media.tv.tuner.DemuxCapabilities getDemuxCapabilities(@NonNull android.content.Context);
- method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.frontend.FrontendInfo getFrontendInfo();
+ method public int cancelScanning();
+ method public int cancelTuning();
+ method public void clearOnTuneEventListener();
+ method public void clearResourceLostListener();
+ method public void close();
+ method public int connectCiCam(int);
+ method public int disconnectCiCam();
+ method public int getAvSyncHwId(@NonNull android.media.tv.tuner.filter.Filter);
+ method public long getAvSyncTime(int);
+ method @Nullable public android.media.tv.tuner.DemuxCapabilities getDemuxCapabilities();
+ method @Nullable public android.media.tv.tuner.frontend.FrontendInfo getFrontendInfo();
method @Nullable public android.media.tv.tuner.frontend.FrontendStatus getFrontendStatus(@NonNull int[]);
method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER) public android.media.tv.tuner.Descrambler openDescrambler();
- method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener);
- method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrRecorder openDvrRecorder(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnRecordStatusChangedListener);
- method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.filter.Filter openFilter(int, int, long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.filter.FilterCallback);
- method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Lnb openLnb(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback);
- method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Lnb openLnbByName(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback);
+ method @Nullable public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener);
+ method @Nullable public android.media.tv.tuner.dvr.DvrRecorder openDvrRecorder(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnRecordStatusChangedListener);
+ method @Nullable public android.media.tv.tuner.filter.Filter openFilter(int, int, long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.filter.FilterCallback);
+ method @Nullable public android.media.tv.tuner.Lnb openLnb(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback);
+ method @Nullable public android.media.tv.tuner.Lnb openLnbByName(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback);
method @Nullable public android.media.tv.tuner.filter.TimeFilter openTimeFilter();
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int scan(@NonNull android.media.tv.tuner.frontend.FrontendSettings, int, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.ScanCallback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int setLnaEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void setOnTuneEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.OnTuneEventListener);
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void setResourceLostListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.Tuner.OnResourceLostListener);
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void shareFrontendFromTuner(@NonNull android.media.tv.tuner.Tuner);
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings);
- method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void updateResourcePriority(int, int);
- }
-
- public static interface Tuner.OnResourceLostListener {
- method public void onResourceLost(@NonNull android.media.tv.tuner.Tuner);
- }
-
- public final class TunerConstants {
+ method public int scan(@NonNull android.media.tv.tuner.frontend.FrontendSettings, int, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.ScanCallback);
+ method public int setLnaEnabled(boolean);
+ method public void setOnTuneEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.OnTuneEventListener);
+ method public void setResourceLostListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.Tuner.OnResourceLostListener);
+ method public void shareFrontendFromTuner(@NonNull android.media.tv.tuner.Tuner);
+ method public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings);
+ method public void updateResourcePriority(int, int);
field public static final int INVALID_AV_SYNC_ID = -1; // 0xffffffff
field public static final int INVALID_FILTER_ID = -1; // 0xffffffff
field public static final int INVALID_STREAM_ID = 65535; // 0xffff
+ field public static final long INVALID_TIMESTAMP = -1L; // 0xffffffffffffffffL
field public static final int INVALID_TS_PID = 65535; // 0xffff
field public static final int RESULT_INVALID_ARGUMENT = 4; // 0x4
field public static final int RESULT_INVALID_STATE = 3; // 0x3
@@ -4912,6 +4901,10 @@
field public static final int SCAN_TYPE_UNDEFINED = 0; // 0x0
}
+ public static interface Tuner.OnResourceLostListener {
+ method public void onResourceLost(@NonNull android.media.tv.tuner.Tuner);
+ }
+
}
package android.media.tv.tuner.dvr {
@@ -5272,7 +5265,6 @@
method public long getSourceTime();
method public long getTimeStamp();
method public int setCurrentTimestamp(long);
- field public static final long TIMESTAMP_UNAVAILABLE = -1L; // 0xffffffffffffffffL
}
public final class TlvFilterConfiguration extends android.media.tv.tuner.filter.FilterConfiguration {
@@ -6225,6 +6217,7 @@
public final class LinkProperties implements android.os.Parcelable {
ctor public LinkProperties(@Nullable android.net.LinkProperties);
+ ctor public LinkProperties(@Nullable android.net.LinkProperties, boolean);
method public boolean addDnsServer(@NonNull java.net.InetAddress);
method public boolean addLinkAddress(@NonNull android.net.LinkAddress);
method public boolean addPcscfServer(@NonNull java.net.InetAddress);
@@ -6247,7 +6240,6 @@
method public boolean isIpv6Provisioned();
method public boolean isProvisioned();
method public boolean isReachable(@NonNull java.net.InetAddress);
- method @NonNull public android.net.LinkProperties makeSensitiveFieldsParcelingCopy();
method public boolean removeDnsServer(@NonNull java.net.InetAddress);
method public boolean removeLinkAddress(@NonNull android.net.LinkAddress);
method public boolean removeRoute(@NonNull android.net.RouteInfo);
@@ -6326,11 +6318,11 @@
}
public final class NetworkCapabilities implements android.os.Parcelable {
- method @NonNull public java.util.List<java.lang.Integer> getAdministratorUids();
+ method @NonNull public int[] getAdministratorUids();
method @Nullable public String getSSID();
method @NonNull public int[] getTransportTypes();
method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
- method @NonNull public android.net.NetworkCapabilities setAdministratorUids(@NonNull java.util.List<java.lang.Integer>);
+ method @NonNull public android.net.NetworkCapabilities setAdministratorUids(@NonNull int[]);
method @NonNull public android.net.NetworkCapabilities setRequestorPackageName(@NonNull String);
method @NonNull public android.net.NetworkCapabilities setRequestorUid(int);
method @NonNull public android.net.NetworkCapabilities setSSID(@Nullable String);
@@ -6408,20 +6400,20 @@
}
public class NetworkStack {
+ method @Nullable public static android.os.IBinder getService();
field public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK";
}
public final class NetworkStats implements android.os.Parcelable {
ctor public NetworkStats(long, int);
method @NonNull public android.net.NetworkStats add(@NonNull android.net.NetworkStats);
- method @NonNull public android.net.NetworkStats addValues(@NonNull android.net.NetworkStats.Entry);
+ method @NonNull public android.net.NetworkStats addEntry(@NonNull android.net.NetworkStats.Entry);
method public int describeContents();
method @NonNull public android.net.NetworkStats subtract(@NonNull android.net.NetworkStats);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStats> CREATOR;
field public static final int DEFAULT_NETWORK_NO = 0; // 0x0
field public static final int DEFAULT_NETWORK_YES = 1; // 0x1
- field @Nullable public static final String IFACE_ALL;
field public static final String IFACE_VT = "vt_data0";
field public static final int METERED_NO = 0; // 0x0
field public static final int METERED_YES = 1; // 0x1
@@ -6550,19 +6542,20 @@
field public static final int TETHERING_WIFI = 0; // 0x0
field public static final int TETHERING_WIFI_P2P = 3; // 0x3
field public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; // 0xc
- field public static final int TETHER_ERROR_DISABLE_NAT_ERROR = 9; // 0x9
- field public static final int TETHER_ERROR_ENABLE_NAT_ERROR = 8; // 0x8
+ field public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9; // 0x9
+ field public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8; // 0x8
field public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; // 0xd
field public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; // 0xa
- field public static final int TETHER_ERROR_MASTER_ERROR = 5; // 0x5
+ field public static final int TETHER_ERROR_INTERNAL_ERROR = 5; // 0x5
field public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; // 0xf
field public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; // 0xe
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 TETHER_ERROR_PROVISIONING_FAILED = 11; // 0xb
field public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; // 0x2
field public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; // 0x6
field public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; // 0x4
field public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; // 0x1
+ field public static final int TETHER_ERROR_UNKNOWN_TYPE = 16; // 0x10
field public static final int TETHER_ERROR_UNSUPPORTED = 3; // 0x3
field public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; // 0x7
field public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2; // 0x2
@@ -6574,29 +6567,19 @@
method public void onTetheringEntitlementResult(int);
}
- public abstract static class TetheringManager.StartTetheringCallback {
- ctor public TetheringManager.StartTetheringCallback();
- method public void onTetheringFailed(int);
- method public void onTetheringStarted();
+ public static interface TetheringManager.StartTetheringCallback {
+ method public default void onTetheringFailed(int);
+ method public default void onTetheringStarted();
}
- public abstract static class TetheringManager.TetheringEventCallback {
- ctor public TetheringManager.TetheringEventCallback();
- method public void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
- method public void onError(@NonNull String, int);
- method public void onOffloadStatusChanged(int);
- method @Deprecated public void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
- method public void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
- method public void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
- method public void onTetheringSupported(boolean);
- method public void onUpstreamChanged(@Nullable android.net.Network);
- }
-
- @Deprecated public static class TetheringManager.TetheringInterfaceRegexps {
- ctor @Deprecated public TetheringManager.TetheringInterfaceRegexps(@NonNull String[], @NonNull String[], @NonNull String[]);
- method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs();
- method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs();
- method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
+ public static interface TetheringManager.TetheringEventCallback {
+ method public default void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
+ method public default void onError(@NonNull String, int);
+ method public default void onOffloadStatusChanged(int);
+ method public default void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+ method public default void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+ method public default void onTetheringSupported(boolean);
+ method public default void onUpstreamChanged(@Nullable android.net.Network);
}
public static class TetheringManager.TetheringRequest {
@@ -6605,9 +6588,14 @@
public static class TetheringManager.TetheringRequest.Builder {
ctor public TetheringManager.TetheringRequest.Builder(int);
method @NonNull public android.net.TetheringManager.TetheringRequest build();
+ method @Nullable public android.net.LinkAddress getClientStaticIpv4Address();
+ method @Nullable public android.net.LinkAddress getLocalIpv4Address();
+ method public boolean getShouldShowEntitlementUi();
+ method public int getTetheringType();
+ method public boolean isExemptFromEntitlementCheck();
method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setSilentProvisioning(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder useStaticIpv4Addresses(@NonNull android.net.LinkAddress);
+ method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setShouldShowEntitlementUi(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setStaticIpv4Addresses(@NonNull android.net.LinkAddress, @NonNull android.net.LinkAddress);
}
public class TrafficStats {
@@ -6821,21 +6809,17 @@
package android.net.netstats.provider {
- public abstract class AbstractNetworkStatsProvider {
- ctor public AbstractNetworkStatsProvider();
- method public abstract void requestStatsUpdate(int);
- method public abstract void setAlert(long);
- method public abstract void setLimit(@NonNull String, long);
+ public abstract class NetworkStatsProvider {
+ ctor public NetworkStatsProvider();
+ method public void notifyAlertReached();
+ method public void notifyLimitReached();
+ method public void notifyStatsUpdated(int, @NonNull android.net.NetworkStats, @NonNull android.net.NetworkStats);
+ method public abstract void onRequestStatsUpdate(int);
+ method public abstract void onSetAlert(long);
+ method public abstract void onSetLimit(@NonNull String, long);
field public static final int QUOTA_UNLIMITED = -1; // 0xffffffff
}
- public class NetworkStatsProviderCallback {
- method public void onAlertReached();
- method public void onLimitReached();
- method public void onStatsUpdated(int, @NonNull android.net.NetworkStats, @NonNull android.net.NetworkStats);
- method public void unregister();
- }
-
}
package android.net.sip {
@@ -7459,7 +7443,15 @@
}
public final class WifiMigration {
+ method @Nullable public static java.io.InputStream convertAndRetrieveSharedConfigStoreFile(int);
+ method @Nullable public static java.io.InputStream convertAndRetrieveUserConfigStoreFile(int, @NonNull android.os.UserHandle);
method @NonNull public static android.net.wifi.WifiMigration.SettingsMigrationData loadFromSettings(@NonNull android.content.Context);
+ method public static void removeSharedConfigStoreFile(int);
+ method public static void removeUserConfigStoreFile(int, @NonNull android.os.UserHandle);
+ field public static final int STORE_FILE_SHARED_GENERAL = 0; // 0x0
+ field public static final int STORE_FILE_SHARED_SOFTAP = 1; // 0x1
+ field public static final int STORE_FILE_USER_GENERAL = 2; // 0x2
+ field public static final int STORE_FILE_USER_NETWORK_SUGGESTIONS = 3; // 0x3
}
public static final class WifiMigration.SettingsMigrationData implements android.os.Parcelable {
@@ -8896,6 +8888,7 @@
method @BinderThread public abstract void onRevokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull String, @NonNull java.util.function.Consumer<java.util.Map<java.lang.String,java.util.List<java.lang.String>>>);
method @BinderThread public abstract void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull String, @NonNull String, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @BinderThread public void onStageAndApplyRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
+ method @BinderThread public void onUpdateUserSensitivePermissionFlags(int, @NonNull java.util.concurrent.Executor, @NonNull Runnable);
method @BinderThread public void onUpdateUserSensitivePermissionFlags(int, @NonNull Runnable);
field public static final String SERVICE_INTERFACE = "android.permission.PermissionControllerService";
}
@@ -9292,7 +9285,6 @@
field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
field public static final String CARRIER_APP_NAMES = "carrier_app_names";
field public static final String CARRIER_APP_WHITELIST = "carrier_app_whitelist";
- field public static final String COMMON_CRITERIA_MODE = "common_criteria_mode";
field public static final String DEFAULT_SM_DP_PLUS = "default_sm_dp_plus";
field public static final String DEVICE_DEMO_MODE = "device_demo_mode";
field public static final String DEVICE_PROVISIONING_MOBILE_DATA_ENABLED = "device_provisioning_mobile_data";
@@ -9352,32 +9344,6 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE) public static boolean putString(@NonNull android.content.ContentResolver, @NonNull String, @Nullable String, boolean);
}
- public static interface Telephony.CarrierColumns extends android.provider.BaseColumns {
- field @NonNull public static final android.net.Uri CONTENT_URI;
- field public static final String EXPIRATION_TIME = "expiration_time";
- field public static final String KEY_IDENTIFIER = "key_identifier";
- field public static final String KEY_TYPE = "key_type";
- field public static final String LAST_MODIFIED = "last_modified";
- field public static final String MCC = "mcc";
- field public static final String MNC = "mnc";
- field public static final String MVNO_MATCH_DATA = "mvno_match_data";
- field public static final String MVNO_TYPE = "mvno_type";
- field public static final String PUBLIC_KEY = "public_key";
- }
-
- public static final class Telephony.CarrierId.All implements android.provider.BaseColumns {
- field public static final String APN = "apn";
- field @NonNull public static final android.net.Uri CONTENT_URI;
- field public static final String GID1 = "gid1";
- field public static final String GID2 = "gid2";
- field public static final String ICCID_PREFIX = "iccid_prefix";
- field public static final String IMSI_PREFIX_XPATTERN = "imsi_prefix_xpattern";
- field public static final String MCCMNC = "mccmnc";
- field public static final String PLMN = "plmn";
- field public static final String PRIVILEGE_ACCESS_RULE = "privilege_access_rule";
- field public static final String SPN = "spn";
- }
-
public static final class Telephony.Carriers implements android.provider.BaseColumns {
field public static final String APN_SET_ID = "apn_set_id";
field public static final int CARRIER_EDITED = 4; // 0x4
@@ -9541,7 +9507,7 @@
package android.se.omapi {
public final class Reader {
- method @RequiresPermission(android.Manifest.permission.SECURE_ELEMENT_PRIVILEGED) public boolean reset();
+ method @RequiresPermission(android.Manifest.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION) public boolean reset();
}
}
@@ -9802,7 +9768,6 @@
method @NonNull public android.service.autofill.augmented.FillResponse build();
method @NonNull public android.service.autofill.augmented.FillResponse.Builder setClientState(@NonNull android.os.Bundle);
method @NonNull public android.service.autofill.augmented.FillResponse.Builder setFillWindow(@NonNull android.service.autofill.augmented.FillWindow);
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineActions(@NonNull java.util.List<android.service.autofill.InlineAction>);
method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineSuggestions(@NonNull java.util.List<android.service.autofill.Dataset>);
}
@@ -10718,27 +10683,6 @@
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR;
}
- public final class CallForwardingInfo implements android.os.Parcelable {
- ctor public CallForwardingInfo(int, int, @Nullable String, int);
- method public int describeContents();
- method @Nullable public String getNumber();
- method public int getReason();
- method public int getStatus();
- method public int getTimeoutSeconds();
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallForwardingInfo> CREATOR;
- field public static final int REASON_ALL = 4; // 0x4
- field public static final int REASON_ALL_CONDITIONAL = 5; // 0x5
- field public static final int REASON_BUSY = 1; // 0x1
- field public static final int REASON_NOT_REACHABLE = 3; // 0x3
- field public static final int REASON_NO_REPLY = 2; // 0x2
- field public static final int REASON_UNCONDITIONAL = 0; // 0x0
- field public static final int STATUS_ACTIVE = 1; // 0x1
- field public static final int STATUS_FDN_CHECK_FAILURE = 2; // 0x2
- field public static final int STATUS_INACTIVE = 0; // 0x0
- field public static final int STATUS_NOT_SUPPORTED = 4; // 0x4
- field public static final int STATUS_UNKNOWN_ERROR = 3; // 0x3
- }
-
public final class CallQuality implements android.os.Parcelable {
ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int);
ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean);
@@ -11119,7 +11063,6 @@
method public void onRadioPowerStateChanged(int);
method public void onSrvccStateChanged(int);
method public void onVoiceActivationStateChanged(int);
- field @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) public static final int LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH = 512; // 0x200
field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
@@ -11150,7 +11093,6 @@
}
public final class PreciseDataConnectionState implements android.os.Parcelable {
- ctor public PreciseDataConnectionState(int, int, int, @NonNull String, @Nullable android.net.LinkProperties, int, @Nullable android.telephony.data.ApnSetting);
method @Deprecated @NonNull public String getDataConnectionApn();
method @Deprecated public int getDataConnectionApnTypeBitMask();
method @Deprecated public int getDataConnectionFailCause();
@@ -11502,8 +11444,6 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes();
method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication();
- method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CallForwardingInfo getCallForwarding(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCallWaitingStatus();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
@@ -11584,8 +11524,6 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAlwaysAllowMmsData(boolean);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCallForwarding(@NonNull android.telephony.CallForwardingInfo);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCallWaitingStatus(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
@@ -11624,18 +11562,10 @@
field public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED";
field public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED = "android.intent.action.EMERGENCY_CALL_STATE_CHANGED";
field public static final String ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE = "com.android.omadm.service.CONFIGURATION_UPDATE";
- field public static final String ACTION_SERVICE_PROVIDERS_UPDATED = "android.telephony.action.SERVICE_PROVIDERS_UPDATED";
field public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS = "android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS";
field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
- field public static final int CALL_WAITING_STATUS_ACTIVE = 1; // 0x1
- field public static final int CALL_WAITING_STATUS_INACTIVE = 2; // 0x2
- field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4
- field public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; // 0x3
- field public static final int CARD_POWER_DOWN = 0; // 0x0
- field public static final int CARD_POWER_UP = 1; // 0x1
- field public static final int CARD_POWER_UP_PASS_THROUGH = 2; // 0x2
field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
@@ -11646,7 +11576,6 @@
field public static final String EXTRA_APN_PROTOCOL_INT = "apnProtoInt";
field @Deprecated public static final String EXTRA_APN_TYPE = "apnType";
field public static final String EXTRA_APN_TYPE_INT = "apnTypeInt";
- field public static final String EXTRA_DATA_SPN = "android.telephony.extra.DATA_SPN";
field public static final String EXTRA_DEFAULT_NETWORK_AVAILABLE = "defaultNetworkAvailable";
field public static final String EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE = "android.telephony.extra.DEFAULT_SUBSCRIPTION_SELECT_TYPE";
field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL = 4; // 0x4
@@ -11659,16 +11588,12 @@
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_PLMN = "android.telephony.extra.PLMN";
field public static final String EXTRA_REDIRECTION_URL = "redirectionUrl";
- field public static final String EXTRA_SHOW_PLMN = "android.telephony.extra.SHOW_PLMN";
- field public static final String EXTRA_SHOW_SPN = "android.telephony.extra.SHOW_SPN";
field public static final String EXTRA_SIM_COMBINATION_NAMES = "android.telephony.extra.SIM_COMBINATION_NAMES";
field public static final String EXTRA_SIM_COMBINATION_WARNING_TYPE = "android.telephony.extra.SIM_COMBINATION_WARNING_TYPE";
field public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA = 1; // 0x1
field public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE = 0; // 0x0
field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
- field public static final String EXTRA_SPN = "android.telephony.extra.SPN";
field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
diff --git a/api/test-current.txt b/api/test-current.txt
index a1a652f..632afdf6 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -83,7 +83,6 @@
method public static void resumeAppSwitches() throws android.os.RemoteException;
method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
method @RequiresPermission("android.permission.MANAGE_USERS") public boolean switchUser(@NonNull android.os.UserHandle);
- method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String);
field public static final int PROCESS_CAPABILITY_ALL = 7; // 0x7
field public static final int PROCESS_CAPABILITY_ALL_EXPLICIT = 1; // 0x1
field public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = 6; // 0x6
@@ -112,6 +111,7 @@
method public void setLaunchActivityType(int);
method public void setLaunchTaskId(int);
method public void setLaunchWindowingMode(int);
+ method public void setTaskAlwaysOnTop(boolean);
method public void setTaskOverlay(boolean, boolean);
}
@@ -830,7 +830,6 @@
field public static final String DEVICE_IDLE_CONTROLLER = "deviceidle";
field public static final String DREAM_SERVICE = "dream";
field public static final String ETHERNET_SERVICE = "ethernet";
- field public static final String NETWORK_STACK_SERVICE = "network_stack";
field public static final String PERMISSION_SERVICE = "permission";
field public static final String POWER_WHITELIST_MANAGER = "power_whitelist";
field public static final String ROLLBACK_SERVICE = "rollback";
@@ -965,7 +964,6 @@
method @NonNull public abstract String getServicesSystemSharedLibraryPackageName();
method @NonNull public abstract String getSharedSystemSharedLibraryPackageName();
method @Nullable public String getSystemTextClassifierPackageName();
- method @Nullable public String[] getTelephonyPackageNames();
method @Nullable public String getWellbeingPackageName();
method @RequiresPermission("android.permission.GRANT_RUNTIME_PERMISSIONS") public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void removeOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
@@ -1008,7 +1006,6 @@
field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
field public static final int PROTECTION_FLAG_RETAIL_DEMO = 16777216; // 0x1000000
field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
- field public static final int PROTECTION_FLAG_TELEPHONY = 4194304; // 0x400000
field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000
field public static final int PROTECTION_FLAG_WELLBEING = 131072; // 0x20000
field @Nullable public final String backgroundPermission;
@@ -1356,8 +1353,8 @@
method @Deprecated public void resetCarrierPhase();
method @Deprecated public void resetCarrierPhaseUncertainty();
method public void resetCodeType();
- method public void resetReceiverInterSignalBiasNanos();
- method public void resetReceiverInterSignalBiasUncertaintyNanos();
+ method public void resetFullInterSignalBiasNanos();
+ method public void resetFullInterSignalBiasUncertaintyNanos();
method public void resetSatelliteInterSignalBiasNanos();
method public void resetSatelliteInterSignalBiasUncertaintyNanos();
method public void resetSnrInDb();
@@ -1374,13 +1371,13 @@
method public void setCn0DbHz(double);
method public void setCodeType(@NonNull String);
method public void setConstellationType(int);
+ method public void setFullInterSignalBiasNanos(double);
+ method public void setFullInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
method public void setMultipathIndicator(int);
method public void setPseudorangeRateMetersPerSecond(double);
method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
method public void setReceivedSvTimeNanos(long);
method public void setReceivedSvTimeUncertaintyNanos(long);
- method public void setReceiverInterSignalBiasNanos(double);
- method public void setReceiverInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
method public void setSatelliteInterSignalBiasNanos(double);
method public void setSatelliteInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
method public void setSnrInDb(double);
@@ -1793,6 +1790,7 @@
public final class LinkProperties implements android.os.Parcelable {
ctor public LinkProperties(@Nullable android.net.LinkProperties);
+ ctor public LinkProperties(@Nullable android.net.LinkProperties, boolean);
method public boolean addDnsServer(@NonNull java.net.InetAddress);
method public boolean addLinkAddress(@NonNull android.net.LinkAddress);
method @Nullable public android.net.Uri getCaptivePortalApiUrl();
@@ -1807,7 +1805,6 @@
method public boolean isIpv6Provisioned();
method public boolean isProvisioned();
method public boolean isReachable(@NonNull java.net.InetAddress);
- method @NonNull public android.net.LinkProperties makeSensitiveFieldsParcelingCopy();
method public boolean removeDnsServer(@NonNull java.net.InetAddress);
method public boolean removeLinkAddress(@NonNull android.net.LinkAddress);
method public boolean removeRoute(@NonNull android.net.RouteInfo);
@@ -1833,6 +1830,7 @@
}
public class NetworkStack {
+ method @Nullable public static android.os.IBinder getService();
field public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK";
}
@@ -1923,19 +1921,20 @@
field public static final int TETHERING_WIFI = 0; // 0x0
field public static final int TETHERING_WIFI_P2P = 3; // 0x3
field public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; // 0xc
- field public static final int TETHER_ERROR_DISABLE_NAT_ERROR = 9; // 0x9
- field public static final int TETHER_ERROR_ENABLE_NAT_ERROR = 8; // 0x8
+ field public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9; // 0x9
+ field public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8; // 0x8
field public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; // 0xd
field public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; // 0xa
- field public static final int TETHER_ERROR_MASTER_ERROR = 5; // 0x5
+ field public static final int TETHER_ERROR_INTERNAL_ERROR = 5; // 0x5
field public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; // 0xf
field public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; // 0xe
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 TETHER_ERROR_PROVISIONING_FAILED = 11; // 0xb
field public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; // 0x2
field public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; // 0x6
field public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; // 0x4
field public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; // 0x1
+ field public static final int TETHER_ERROR_UNKNOWN_TYPE = 16; // 0x10
field public static final int TETHER_ERROR_UNSUPPORTED = 3; // 0x3
field public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; // 0x7
field public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2; // 0x2
@@ -1947,29 +1946,19 @@
method public void onTetheringEntitlementResult(int);
}
- public abstract static class TetheringManager.StartTetheringCallback {
- ctor public TetheringManager.StartTetheringCallback();
- method public void onTetheringFailed(int);
- method public void onTetheringStarted();
+ public static interface TetheringManager.StartTetheringCallback {
+ method public default void onTetheringFailed(int);
+ method public default void onTetheringStarted();
}
- public abstract static class TetheringManager.TetheringEventCallback {
- ctor public TetheringManager.TetheringEventCallback();
- method public void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
- method public void onError(@NonNull String, int);
- method public void onOffloadStatusChanged(int);
- method @Deprecated public void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
- method public void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
- method public void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
- method public void onTetheringSupported(boolean);
- method public void onUpstreamChanged(@Nullable android.net.Network);
- }
-
- @Deprecated public static class TetheringManager.TetheringInterfaceRegexps {
- ctor @Deprecated public TetheringManager.TetheringInterfaceRegexps(@NonNull String[], @NonNull String[], @NonNull String[]);
- method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs();
- method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs();
- method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
+ public static interface TetheringManager.TetheringEventCallback {
+ method public default void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
+ method public default void onError(@NonNull String, int);
+ method public default void onOffloadStatusChanged(int);
+ method public default void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+ method public default void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+ method public default void onTetheringSupported(boolean);
+ method public default void onUpstreamChanged(@Nullable android.net.Network);
}
public static class TetheringManager.TetheringRequest {
@@ -1978,9 +1967,14 @@
public static class TetheringManager.TetheringRequest.Builder {
ctor public TetheringManager.TetheringRequest.Builder(int);
method @NonNull public android.net.TetheringManager.TetheringRequest build();
+ method @Nullable public android.net.LinkAddress getClientStaticIpv4Address();
+ method @Nullable public android.net.LinkAddress getLocalIpv4Address();
+ method public boolean getShouldShowEntitlementUi();
+ method public int getTetheringType();
+ method public boolean isExemptFromEntitlementCheck();
method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean);
- method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setSilentProvisioning(boolean);
- method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder useStaticIpv4Addresses(@NonNull android.net.LinkAddress);
+ method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setShouldShowEntitlementUi(boolean);
+ method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setStaticIpv4Addresses(@NonNull android.net.LinkAddress, @NonNull android.net.LinkAddress);
}
public class TrafficStats {
@@ -3263,7 +3257,6 @@
method @NonNull public android.service.autofill.augmented.FillResponse build();
method @NonNull public android.service.autofill.augmented.FillResponse.Builder setClientState(@NonNull android.os.Bundle);
method @NonNull public android.service.autofill.augmented.FillResponse.Builder setFillWindow(@NonNull android.service.autofill.augmented.FillWindow);
- method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineActions(@NonNull java.util.List<android.service.autofill.InlineAction>);
method @NonNull public android.service.autofill.augmented.FillResponse.Builder setInlineSuggestions(@NonNull java.util.List<android.service.autofill.Dataset>);
}
diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt
index 94db346..caf8fdb 100644
--- a/api/test-lint-baseline.txt
+++ b/api/test-lint-baseline.txt
@@ -421,9 +421,9 @@
GetterSetterNames: android.location.GnssMeasurement#setCodeType(String):
-GetterSetterNames: android.location.GnssMeasurement#setReceiverInterSignalBiasNanos(double):
+GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasNanos(double):
-GetterSetterNames: android.location.GnssMeasurement#setReceiverInterSignalBiasUncertaintyNanos(double):
+GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasUncertaintyNanos(double):
GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasNanos(double):
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index d79123b..60d1ac7 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -267,28 +267,29 @@
bool workerDone = false;
FdBuffer buffer;
- // Create shared data and pipe
- WorkerThreadData data(this);
- if (!data.pipe.init()) {
+ // Create shared data and pipe. Don't put data on the stack since this thread may exit early.
+ sp<WorkerThreadData> data = new WorkerThreadData(this);
+ if (!data->pipe.init()) {
return -errno;
}
-
- std::thread([&]() {
+ data->incStrong(this);
+ std::thread([data, this]() {
// Don't crash the service if writing to a closed pipe (may happen if dumping times out)
signal(SIGPIPE, sigpipe_handler);
- status_t err = data.section->BlockingCall(data.pipe.writeFd());
+ status_t err = data->section->BlockingCall(data->pipe.writeFd());
{
- std::unique_lock<std::mutex> lock(data.lock);
- data.workerDone = true;
- data.workerError = err;
+ std::scoped_lock<std::mutex> lock(data->lock);
+ data->workerDone = true;
+ data->workerError = err;
// unique_fd is not thread safe. If we don't lock it, reset() may pause half way while
// the other thread executes to the end, calling ~Fpipe, which is a race condition.
- data.pipe.writeFd().reset();
+ data->pipe.writeFd().reset();
}
+ data->decStrong(this);
}).detach();
// Loop reading until either the timeout or the worker side is done (i.e. eof).
- err = buffer.read(data.pipe.readFd().get(), this->timeoutMs);
+ err = buffer.read(data->pipe.readFd().get(), this->timeoutMs);
if (err != NO_ERROR) {
ALOGE("[%s] reader failed with error '%s'", this->name.string(), strerror(-err));
}
@@ -296,13 +297,13 @@
// If the worker side is finished, then return its error (which may overwrite
// our possible error -- but it's more interesting anyway). If not, then we timed out.
{
- std::unique_lock<std::mutex> lock(data.lock);
- data.pipe.close();
- if (data.workerError != NO_ERROR) {
- err = data.workerError;
+ std::scoped_lock<std::mutex> lock(data->lock);
+ data->pipe.close();
+ if (data->workerError != NO_ERROR) {
+ err = data->workerError;
ALOGE("[%s] worker failed with error '%s'", this->name.string(), strerror(-err));
}
- workerDone = data.workerDone;
+ workerDone = data->workerDone;
}
writer->setSectionStats(buffer);
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 33bfe51..4529dff 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -189,6 +189,34 @@
],
}
+genrule {
+ name: "statslog_statsdtest.h",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog_statsdtest.h --module statsdtest --namespace android,os,statsd,util",
+ out: [
+ "statslog_statsdtest.h",
+ ],
+}
+
+genrule {
+ name: "statslog_statsdtest.cpp",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog_statsdtest.cpp --module statsdtest --namespace android,os,statsd,util --importHeader statslog_statsdtest.h",
+ out: [
+ "statslog_statsdtest.cpp",
+ ],
+}
+
+cc_library_static {
+ name: "libstatslog_statsdtest",
+ generated_sources: ["statslog_statsdtest.cpp"],
+ generated_headers: ["statslog_statsdtest.h"],
+ export_generated_headers: ["statslog_statsdtest.h"],
+ shared_libs: [
+ "libstatssocket",
+ ]
+}
+
cc_library_static {
name: "libstatslog_statsd",
generated_sources: ["statslog_statsd.cpp"],
@@ -331,7 +359,7 @@
static_libs: [
"libgmock",
"libplatformprotos",
- "libstatslog", //TODO(b/150976524): remove this when the tests no longer hardcode atoms.
+ "libstatslog_statsdtest",
"libstatssocket_private",
],
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 713e923..f0a5b51 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -81,12 +81,16 @@
BleScanStateChanged ble_scan_state_changed = 2 [(module) = "bluetooth"];
ProcessStateChanged process_state_changed = 3 [(module) = "framework"];
BleScanResultReceived ble_scan_result_received = 4 [(module) = "bluetooth"];
- SensorStateChanged sensor_state_changed = 5 [(module) = "framework"];
+ SensorStateChanged sensor_state_changed =
+ 5 [(module) = "framework", (module) = "statsdtest"];
GpsScanStateChanged gps_scan_state_changed = 6 [(module) = "framework"];
- SyncStateChanged sync_state_changed = 7 [(module) = "framework"];
- ScheduledJobStateChanged scheduled_job_state_changed = 8 [(module) = "framework"];
- ScreenBrightnessChanged screen_brightness_changed = 9 [(module) = "framework"];
- WakelockStateChanged wakelock_state_changed = 10 [(module) = "framework"];
+ SyncStateChanged sync_state_changed = 7 [(module) = "framework", (module) = "statsdtest"];
+ ScheduledJobStateChanged scheduled_job_state_changed =
+ 8 [(module) = "framework", (module) = "statsdtest"];
+ ScreenBrightnessChanged screen_brightness_changed =
+ 9 [(module) = "framework", (module) = "statsdtest"];
+ WakelockStateChanged wakelock_state_changed =
+ 10 [(module) = "framework", (module) = "statsdtest"];
LongPartialWakelockStateChanged long_partial_wakelock_state_changed =
11 [(module) = "framework"];
MobileRadioPowerStateChanged mobile_radio_power_state_changed = 12 [(module) = "framework"];
@@ -98,17 +102,22 @@
CachedKillReported cached_kill_reported = 17 [(module) = "framework"];
ProcessMemoryStatReported process_memory_stat_reported = 18 [(module) = "framework"];
LauncherUIChanged launcher_event = 19 [(module) = "sysui"];
- BatterySaverModeStateChanged battery_saver_mode_state_changed = 20 [(module) = "framework"];
+ BatterySaverModeStateChanged battery_saver_mode_state_changed =
+ 20 [(module) = "framework", (module) = "statsdtest"];
DeviceIdleModeStateChanged device_idle_mode_state_changed = 21 [(module) = "framework"];
DeviceIdlingModeStateChanged device_idling_mode_state_changed = 22 [(module) = "framework"];
AudioStateChanged audio_state_changed = 23 [(module) = "framework"];
MediaCodecStateChanged media_codec_state_changed = 24 [(module) = "framework"];
CameraStateChanged camera_state_changed = 25 [(module) = "framework"];
FlashlightStateChanged flashlight_state_changed = 26 [(module) = "framework"];
- UidProcessStateChanged uid_process_state_changed = 27 [(module) = "framework"];
- ProcessLifeCycleStateChanged process_life_cycle_state_changed = 28 [(module) = "framework"];
- ScreenStateChanged screen_state_changed = 29 [(module) = "framework"];
- BatteryLevelChanged battery_level_changed = 30 [(module) = "framework"];
+ UidProcessStateChanged uid_process_state_changed =
+ 27 [(module) = "framework", (module) = "statsdtest"];
+ ProcessLifeCycleStateChanged process_life_cycle_state_changed =
+ 28 [(module) = "framework", (module) = "statsdtest"];
+ ScreenStateChanged screen_state_changed =
+ 29 [(module) = "framework", (module) = "statsdtest"];
+ BatteryLevelChanged battery_level_changed =
+ 30 [(module) = "framework", (module) = "statsdtest"];
ChargingStateChanged charging_state_changed = 31 [(module) = "framework"];
PluggedStateChanged plugged_state_changed = 32 [(module) = "framework"];
InteractiveStateChanged interactive_state_changed = 33 [(module) = "framework"];
@@ -121,14 +130,15 @@
PhoneSignalStrengthChanged phone_signal_strength_changed = 40 [(module) = "framework"];
SettingChanged setting_changed = 41 [(module) = "framework"];
ActivityForegroundStateChanged activity_foreground_state_changed =
- 42 [(module) = "framework"];
- IsolatedUidChanged isolated_uid_changed = 43 [(module) = "framework", (module) = "statsd"];
+ 42 [(module) = "framework", (module) = "statsdtest"];
+ IsolatedUidChanged isolated_uid_changed =
+ 43 [(module) = "framework", (module) = "statsd", (module) = "statsdtest"];
PacketWakeupOccurred packet_wakeup_occurred = 44 [(module) = "framework"];
WallClockTimeShifted wall_clock_time_shifted = 45 [(module) = "framework"];
AnomalyDetected anomaly_detected = 46 [(module) = "statsd"];
AppBreadcrumbReported app_breadcrumb_reported =
47 [(allow_from_any_uid) = true, (module) = "statsd"];
- AppStartOccurred app_start_occurred = 48 [(module) = "framework"];
+ AppStartOccurred app_start_occurred = 48 [(module) = "framework", (module) = "statsdtest"];
AppStartCanceled app_start_canceled = 49 [(module) = "framework"];
AppStartFullyDrawn app_start_fully_drawn = 50 [(module) = "framework"];
LmkKillOccurred lmk_kill_occurred = 51 [(module) = "lmkd"];
@@ -139,7 +149,8 @@
ShutdownSequenceReported shutdown_sequence_reported = 56 [(module) = "framework"];
BootSequenceReported boot_sequence_reported = 57;
DaveyOccurred davey_occurred = 58 [(allow_from_any_uid) = true, (module) = "statsd"];
- OverlayStateChanged overlay_state_changed = 59 [(module) = "framework"];
+ OverlayStateChanged overlay_state_changed =
+ 59 [(module) = "framework", (module) = "statsdtest"];
ForegroundServiceStateChanged foreground_service_state_changed
= 60 [(module) = "framework"];
CallStateChanged call_state_changed = 61 [(module) = "telecom"];
@@ -160,7 +171,7 @@
MobileConnectionStateChanged mobile_connection_state_changed = 75 [(module) = "telephony"];
MobileRadioTechnologyChanged mobile_radio_technology_changed = 76 [(module) = "telephony"];
UsbDeviceAttached usb_device_attached = 77 [(module) = "framework"];
- AppCrashOccurred app_crash_occurred = 78 [(module) = "framework"];
+ AppCrashOccurred app_crash_occurred = 78 [(module) = "framework", (module) = "statsdtest"];
ANROccurred anr_occurred = 79 [(module) = "framework"];
WTFOccurred wtf_occurred = 80 [(module) = "framework"];
LowMemReported low_mem_reported = 81 [(module) = "framework"];
@@ -398,6 +409,8 @@
256 [(module) = "framework"];
DisplayJankReported display_jank_reported = 257;
AppStandbyBucketChanged app_standby_bucket_changed = 258 [(module) = "framework"];
+ SharesheetStarted sharesheet_started = 259 [(module) = "framework"];
+ RankingSelected ranking_selected = 260 [(module) = "framework"];
SdkExtensionStatus sdk_extension_status = 354;
}
@@ -410,9 +423,9 @@
MobileBytesTransferByFgBg mobile_bytes_transfer_by_fg_bg = 10003 [(module) = "framework"];
BluetoothBytesTransfer bluetooth_bytes_transfer = 10006 [(module) = "framework"];
KernelWakelock kernel_wakelock = 10004 [(module) = "framework"];
- SubsystemSleepState subsystem_sleep_state = 10005;
+ SubsystemSleepState subsystem_sleep_state = 10005 [(module) = "statsdtest"];
CpuTimePerFreq cpu_time_per_freq = 10008 [(module) = "framework"];
- CpuTimePerUid cpu_time_per_uid = 10009 [(module) = "framework"];
+ CpuTimePerUid cpu_time_per_uid = 10009 [(module) = "framework", (module) = "statsdtest"];
CpuTimePerUidFreq cpu_time_per_uid_freq =
10010 [(module) = "framework", (module) = "statsd"];
WifiActivityInfo wifi_activity_info = 10011 [(module) = "framework"];
@@ -420,13 +433,13 @@
BluetoothActivityInfo bluetooth_activity_info = 10007 [(module) = "framework"];
ProcessMemoryState process_memory_state = 10013 [(module) = "framework"];
SystemElapsedRealtime system_elapsed_realtime = 10014 [(module) = "framework"];
- SystemUptime system_uptime = 10015 [(module) = "framework"];
+ SystemUptime system_uptime = 10015 [(module) = "framework", (module) = "statsdtest"];
CpuActiveTime cpu_active_time = 10016 [(module) = "framework"];
- CpuClusterTime cpu_cluster_time = 10017 [(module) = "framework"];
- DiskSpace disk_space = 10018 [deprecated=true];
+ CpuClusterTime cpu_cluster_time = 10017 [(module) = "framework", (module) = "statsdtest"];
+ DiskSpace disk_space = 10018 [deprecated=true, (module) = "statsdtest"];
RemainingBatteryCapacity remaining_battery_capacity = 10019 [(module) = "framework"];
FullBatteryCapacity full_battery_capacity = 10020 [(module) = "framework"];
- Temperature temperature = 10021 [(module) = "framework"];
+ Temperature temperature = 10021 [(module) = "framework", (module) = "statsdtest"];
BinderCalls binder_calls = 10022 [(module) = "framework", (module) = "statsd"];
BinderCallsExceptions binder_calls_exceptions = 10023 [(module) = "framework"];
LooperStats looper_stats = 10024 [(module) = "framework", (module) = "statsd"];
@@ -8914,3 +8927,64 @@
// UsageStatsManager.java.
optional int32 sub_reason = 5;
}
+
+/**
+* Reports a started sharesheet transaction.
+*
+* Logged from:
+* frameworks/base/core/java/com/android/internal/app/ChooserActivity.java
+*/
+message SharesheetStarted {
+ // The event_id (as for UiEventReported).
+ optional int32 event_id = 1;
+ // The calling app's package name.
+ optional string package_name = 2;
+ // An identifier to tie together multiple logs relating to the same share event
+ optional int32 instance_id = 3;
+ // The mime type of the share
+ optional string mime_type = 4;
+ // The number of direct targets the calling app is providing that will be shown.
+ optional int32 num_app_provided_direct_targets = 5;
+ // The number of app targets the calling app is providing that will be shown.
+ optional int32 num_app_provided_app_targets = 6;
+ // True if the share originates from the workprofile
+ optional bool is_workprofile = 7;
+
+ enum SharesheetPreviewType { // Constants from ChooserActivity.java
+ CONTENT_PREVIEW_IMAGE = 1; // The preview shown in the sharesheet is an image.
+ CONTENT_PREVIEW_FILE = 2; // The preview shown in the sharesheet is a file.
+ CONTENT_PREVIEW_TEXT = 3; // The preview shown in the sharesheet is text.
+ }
+ // How the sharesheet preview is presented.
+ optional SharesheetPreviewType previewType = 8;
+
+ enum ResolverActivityIntent { // Intents handled by ResolverActivity.java
+ INTENT_DEFAULT = 0;
+ INTENT_ACTION_VIEW = 1;
+ INTENT_ACTION_EDIT = 2;
+ INTENT_ACTION_SEND = 3;
+ INTENT_ACTION_SENDTO = 4;
+ INTENT_ACTION_SEND_MULTIPLE = 5;
+ INTENT_ACTION_IMAGE_CAPTURE = 6;
+ INTENT_ACTION_MAIN = 7;
+ }
+ // The intent being processed (only SEND and SEND_MULTIPLE are system sharesheet)
+ optional ResolverActivityIntent intentType = 9;
+}
+
+/**
+ * Reports a ranking selection event.
+ *
+ * Logged from:
+ * frameworks/base/core/java/com/android/internal/app/ChooserActivity.java (sharesheet)
+ */
+message RankingSelected {
+ // The event_id (as for UiEventReported).
+ optional int32 event_id = 1;
+ // The relevant app's package name (can be source or picked package).
+ optional string package_name = 2;
+ // An identifier to tie together multiple logs relating to the same share event.
+ optional int32 instance_id = 3;
+ // Which of the ranked targets got picked, default starting position 0.
+ optional int32 position_picked = 4;
+}
diff --git a/cmds/statsd/src/state/StateTracker.h b/cmds/statsd/src/state/StateTracker.h
index aeca2a5..154750e 100644
--- a/cmds/statsd/src/state/StateTracker.h
+++ b/cmds/statsd/src/state/StateTracker.h
@@ -30,7 +30,7 @@
class StateTracker : public virtual RefBase {
public:
- StateTracker(const int32_t atomId, const util::StateAtomFieldOptions& stateAtomInfo);
+ StateTracker(const int32_t atomId, const android::util::StateAtomFieldOptions& stateAtomInfo);
virtual ~StateTracker(){};
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index aec0956..ade25d6 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -23,24 +23,26 @@
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
#include "guardrail/StatsdStats.h"
+using android::util::ProtoOutputStream;
+
namespace android {
namespace os {
namespace statsd {
void writeFieldValueTreeToStream(int tagId, const std::vector<FieldValue>& values,
- util::ProtoOutputStream* protoOutput);
+ ProtoOutputStream* protoOutput);
void writeDimensionToProto(const HashableDimensionKey& dimension, std::set<string> *str_set,
- util::ProtoOutputStream* protoOutput);
+ ProtoOutputStream* protoOutput);
void writeDimensionLeafNodesToProto(const HashableDimensionKey& dimension,
const int dimensionLeafFieldId,
std::set<string> *str_set,
- util::ProtoOutputStream* protoOutput);
+ ProtoOutputStream* protoOutput);
void writeDimensionPathToProto(const std::vector<Matcher>& fieldMatchers,
- util::ProtoOutputStream* protoOutput);
+ ProtoOutputStream* protoOutput);
-void writeStateToProto(const FieldValue& state, util::ProtoOutputStream* protoOutput);
+void writeStateToProto(const FieldValue& state, ProtoOutputStream* protoOutput);
// Convert the TimeUnit enum to the bucket size in millis with a guardrail on
// bucket size.
@@ -73,14 +75,14 @@
// Helper function to write PulledAtomStats to ProtoOutputStream
void writePullerStatsToStream(const std::pair<int, StatsdStats::PulledAtomStats>& pair,
- util::ProtoOutputStream* protoOutput);
+ ProtoOutputStream* protoOutput);
// Helper function to write AtomMetricStats to ProtoOutputStream
void writeAtomMetricStatsToStream(const std::pair<int64_t, StatsdStats::AtomMetricStats> &pair,
- util::ProtoOutputStream *protoOutput);
+ ProtoOutputStream *protoOutput);
template<class T>
-bool parseProtoOutputStream(util::ProtoOutputStream& protoOutput, T* message) {
+bool parseProtoOutputStream(ProtoOutputStream& protoOutput, T* message) {
std::string pbBytes;
sp<android::util::ProtoReader> reader = protoOutput.data();
while (reader->readBuffer() != NULL) {
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 81d6f72..d6498f4 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -21,7 +21,7 @@
#include "logd/LogEvent.h"
#include "packages/UidMap.h"
#include "storage/StorageManager.h"
-#include "statslog.h"
+#include "statslog_statsdtest.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index af6de06..a49c18f 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -18,7 +18,7 @@
#include "guardrail/StatsdStats.h"
#include "logd/LogEvent.h"
#include "hash.h"
-#include "statslog.h"
+#include "statslog_statsdtest.h"
#include "statsd_test_util.h"
#include <android/util/ProtoOutputStream.h>
@@ -49,7 +49,7 @@
// StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
// [](const ConfigKey& key) { return true; },
// [](const int&, const vector<int64_t>&) {return true;});
-// LogEvent addEvent(android::util::ISOLATED_UID_CHANGED, 1);
+// LogEvent addEvent(util::ISOLATED_UID_CHANGED, 1);
// addEvent.write(100); // parent UID
// addEvent.write(101); // isolated UID
// addEvent.write(1); // Indicates creation.
@@ -60,7 +60,7 @@
// p.OnLogEvent(&addEvent);
// EXPECT_EQ(100, m->getHostUidOrSelf(101));
//
-// LogEvent removeEvent(android::util::ISOLATED_UID_CHANGED, 1);
+// LogEvent removeEvent(util::ISOLATED_UID_CHANGED, 1);
// removeEvent.write(100); // parent UID
// removeEvent.write(101); // isolated UID
// removeEvent.write(0); // Indicates removal.
diff --git a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
index e0eebef..9c6965d 100644
--- a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
@@ -39,7 +39,7 @@
countMetric->set_id(123456);
countMetric->set_what(wakelockAcquireMatcher.id());
*countMetric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
- android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
countMetric->set_bucket(FIVE_MINUTES);
auto alert = config.add_alert();
@@ -83,12 +83,12 @@
std::vector<int> attributionUids5 = {222};
std::vector<string> attributionTags5 = {"GMSCoreModule1"};
- FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+ FieldValue fieldValue1(Field(util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)111));
HashableDimensionKey whatKey1({fieldValue1});
MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
- FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+ FieldValue fieldValue2(Field(util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)222));
HashableDimensionKey whatKey2({fieldValue2});
MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
@@ -194,7 +194,7 @@
std::vector<int> attributionUids2 = {111, 222};
std::vector<string> attributionTags2 = {"App1", "GMSCoreModule1"};
- FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+ FieldValue fieldValue1(Field(util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)111));
HashableDimensionKey whatKey1({fieldValue1});
MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
diff --git a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
index fe45b55..4f9f315 100644
--- a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
@@ -45,7 +45,7 @@
auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
FieldMatcher dimensions = CreateAttributionUidDimensions(
- android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
dimensions.add_child()->set_field(3); // The wakelock tag is set in field 3 of the wakelock.
*holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
holdingWakelockPredicate.mutable_simple_predicate()->set_count_nesting(nesting);
@@ -57,7 +57,7 @@
durationMetric->set_condition(screenIsOffPredicate.id());
durationMetric->set_aggregation_type(aggregationType);
*durationMetric->mutable_dimensions_in_what() =
- CreateAttributionUidDimensions(android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
durationMetric->set_bucket(FIVE_MINUTES);
auto alert = config.add_alert();
@@ -79,13 +79,13 @@
std::vector<string> attributionTags3 = {"GMSCoreModule1"};
MetricDimensionKey dimensionKey1(
- HashableDimensionKey({FieldValue(Field(android::util::WAKELOCK_STATE_CHANGED,
+ HashableDimensionKey({FieldValue(Field(util::WAKELOCK_STATE_CHANGED,
(int32_t)0x02010101),
Value((int32_t)111))}),
DEFAULT_DIMENSION_KEY);
MetricDimensionKey dimensionKey2(
- HashableDimensionKey({FieldValue(Field(android::util::WAKELOCK_STATE_CHANGED,
+ HashableDimensionKey({FieldValue(Field(util::WAKELOCK_STATE_CHANGED,
(int32_t)0x02010101), Value((int32_t)222))}),
DEFAULT_DIMENSION_KEY);
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index 9e743f7..52229e2 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -48,7 +48,7 @@
countMetric->set_what(wakelockAcquireMatcher.id());
*countMetric->mutable_dimensions_in_what() =
CreateAttributionUidAndTagDimensions(
- android::util::WAKELOCK_STATE_CHANGED, {position});
+ util::WAKELOCK_STATE_CHANGED, {position});
countMetric->set_bucket(FIVE_MINUTES);
return config;
}
@@ -164,7 +164,7 @@
auto data = countMetrics.data(0);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
+ util::WAKELOCK_STATE_CHANGED, 111, "App1");
EXPECT_EQ(data.bucket_info_size(), 2);
EXPECT_EQ(data.bucket_info(0).count(), 2);
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
@@ -176,7 +176,7 @@
data = countMetrics.data(1);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 222,
+ util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule1");
EXPECT_EQ(data.bucket_info_size(), 2);
EXPECT_EQ(data.bucket_info(0).count(), 1);
@@ -188,7 +188,7 @@
data = countMetrics.data(2);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 222,
+ util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule3");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
@@ -198,7 +198,7 @@
data = countMetrics.data(3);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 444,
+ util::WAKELOCK_STATE_CHANGED, 444,
"GMSCoreModule2");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
@@ -277,7 +277,7 @@
auto data = countMetrics.data(0);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 222,
+ util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule1");
EXPECT_EQ(2, data.bucket_info_size());
EXPECT_EQ(1, data.bucket_info(0).count());
@@ -289,26 +289,26 @@
EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
data = countMetrics.data(1);
- ValidateUidDimension(data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222);
+ ValidateUidDimension(data.dimensions_in_what(), 0, util::WAKELOCK_STATE_CHANGED, 222);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 0,
- android::util::WAKELOCK_STATE_CHANGED, 222,
+ util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule1");
- ValidateUidDimension(data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
+ ValidateUidDimension(data.dimensions_in_what(), 1, util::WAKELOCK_STATE_CHANGED, 333);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 1,
- android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+ util::WAKELOCK_STATE_CHANGED, 333, "App3");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
data = countMetrics.data(2);
- ValidateUidDimension(data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444);
+ ValidateUidDimension(data.dimensions_in_what(), 0, util::WAKELOCK_STATE_CHANGED, 444);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 0,
- android::util::WAKELOCK_STATE_CHANGED, 444,
+ util::WAKELOCK_STATE_CHANGED, 444,
"GMSCoreModule2");
- ValidateUidDimension(data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
+ ValidateUidDimension(data.dimensions_in_what(), 1, util::WAKELOCK_STATE_CHANGED, 222);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 1,
- android::util::WAKELOCK_STATE_CHANGED, 222,
+ util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule1");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
@@ -317,31 +317,31 @@
EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(3);
- ValidateUidDimension(data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
+ ValidateUidDimension(data.dimensions_in_what(), 0, util::WAKELOCK_STATE_CHANGED, 111);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 0,
- android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
- ValidateUidDimension(data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
+ util::WAKELOCK_STATE_CHANGED, 111, "App1");
+ ValidateUidDimension(data.dimensions_in_what(), 1, util::WAKELOCK_STATE_CHANGED, 222);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 1,
- android::util::WAKELOCK_STATE_CHANGED, 222,
+ util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule1");
- ValidateUidDimension(data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
+ ValidateUidDimension(data.dimensions_in_what(), 2, util::WAKELOCK_STATE_CHANGED, 333);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 2,
- android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+ util::WAKELOCK_STATE_CHANGED, 333, "App3");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(4);
- ValidateUidDimension(data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
+ ValidateUidDimension(data.dimensions_in_what(), 0, util::WAKELOCK_STATE_CHANGED, 111);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 0,
- android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
- ValidateUidDimension(data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
+ util::WAKELOCK_STATE_CHANGED, 111, "App1");
+ ValidateUidDimension(data.dimensions_in_what(), 1, util::WAKELOCK_STATE_CHANGED, 333);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 1,
- android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
- ValidateUidDimension(data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222);
+ util::WAKELOCK_STATE_CHANGED, 333, "App3");
+ ValidateUidDimension(data.dimensions_in_what(), 2, util::WAKELOCK_STATE_CHANGED, 222);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 2,
- android::util::WAKELOCK_STATE_CHANGED, 222,
+ util::WAKELOCK_STATE_CHANGED, 222,
"GMSCoreModule1");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
@@ -349,16 +349,16 @@
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(5);
- ValidateUidDimension(data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
+ ValidateUidDimension(data.dimensions_in_what(), 0, util::WAKELOCK_STATE_CHANGED, 111);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 0,
- android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
- ValidateUidDimension(data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444);
+ util::WAKELOCK_STATE_CHANGED, 111, "App1");
+ ValidateUidDimension(data.dimensions_in_what(), 1, util::WAKELOCK_STATE_CHANGED, 444);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 1,
- android::util::WAKELOCK_STATE_CHANGED, 444,
+ util::WAKELOCK_STATE_CHANGED, 444,
"GMSCoreModule2");
- ValidateUidDimension(data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
+ ValidateUidDimension(data.dimensions_in_what(), 2, util::WAKELOCK_STATE_CHANGED, 333);
ValidateAttributionUidAndTagDimension(data.dimensions_in_what(), 2,
- android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+ util::WAKELOCK_STATE_CHANGED, 333, "App3");
EXPECT_EQ(data.bucket_info_size(), 1);
EXPECT_EQ(data.bucket_info(0).count(), 1);
EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
diff --git a/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp b/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
index 102bb1e..16adbdd 100644
--- a/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
@@ -39,7 +39,7 @@
countMetric->set_id(123456);
countMetric->set_what(wakelockAcquireMatcher.id());
*countMetric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
- android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
countMetric->set_bucket(FIVE_MINUTES);
auto alert = config.add_alert();
@@ -74,12 +74,12 @@
std::vector<int> attributionUids1 = {111};
std::vector<string> attributionTags1 = {"App1"};
- FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+ FieldValue fieldValue1(Field(util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)111));
HashableDimensionKey whatKey1({fieldValue1});
MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
- FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+ FieldValue fieldValue2(Field(util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
Value((int32_t)222));
HashableDimensionKey whatKey2({fieldValue2});
MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
diff --git a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
index 2cd7854..69326cb 100644
--- a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
@@ -365,7 +365,7 @@
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
auto appCrashMatcher =
- CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", android::util::APP_CRASH_OCCURRED);
+ CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", util::APP_CRASH_OCCURRED);
*config.add_atom_matcher() = appCrashMatcher;
auto state = CreateUidProcessState();
@@ -381,7 +381,7 @@
MetricStateLink* stateLink = countMetric->add_state_link();
stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
auto fieldsInWhat = stateLink->mutable_fields_in_what();
- *fieldsInWhat = CreateDimensions(android::util::APP_CRASH_OCCURRED, {1 /*uid*/});
+ *fieldsInWhat = CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
auto fieldsInState = stateLink->mutable_fields_in_state();
*fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /*uid*/});
@@ -551,7 +551,7 @@
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
auto appCrashMatcher =
- CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", android::util::APP_CRASH_OCCURRED);
+ CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", util::APP_CRASH_OCCURRED);
*config.add_atom_matcher() = appCrashMatcher;
auto state1 = CreateScreenStateWithOnOffMap();
@@ -571,7 +571,7 @@
MetricStateLink* stateLink = countMetric->add_state_link();
stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
auto fieldsInWhat = stateLink->mutable_fields_in_what();
- *fieldsInWhat = CreateDimensions(android::util::APP_CRASH_OCCURRED, {1 /*uid*/});
+ *fieldsInWhat = CreateDimensions(util::APP_CRASH_OCCURRED, {1 /*uid*/});
auto fieldsInState = stateLink->mutable_fields_in_state();
*fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /*uid*/});
diff --git a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
index b586b06..ae2a0f5 100644
--- a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
@@ -456,14 +456,14 @@
auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
// The predicate is dimensioning by first attribution node by uid.
- FieldMatcher dimensions = CreateAttributionUidDimensions(android::util::WAKELOCK_STATE_CHANGED,
+ FieldMatcher dimensions = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED,
{Position::FIRST});
*holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
*config.add_predicate() = holdingWakelockPredicate;
auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
*isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
- CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
+ CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
*config.add_predicate() = isInBackgroundPredicate;
auto durationMetric = config.add_duration_metric();
@@ -473,17 +473,17 @@
durationMetric->set_aggregation_type(DurationMetric::SUM);
// The metric is dimensioning by first attribution node and only by uid.
*durationMetric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
- android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
durationMetric->set_bucket(FIVE_MINUTES);
// Links between wakelock state atom and condition of app is in background.
auto links = durationMetric->add_links();
links->set_condition(isInBackgroundPredicate.id());
auto dimensionWhat = links->mutable_fields_in_what();
- dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
+ dimensionWhat->set_field(util::WAKELOCK_STATE_CHANGED);
dimensionWhat->add_child()->set_field(1); // uid field.
*links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
- android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
+ util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
ConfigKey cfgKey;
uint64_t bucketStartTimeNs = 10000000000;
@@ -536,7 +536,7 @@
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// Validate dimension value.
ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, appUid);
+ util::WAKELOCK_STATE_CHANGED, appUid);
// Validate bucket info.
EXPECT_EQ(1, data.bucket_info_size());
@@ -558,14 +558,14 @@
auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
// The predicate is dimensioning by first attribution node by uid.
- FieldMatcher dimensions = CreateAttributionUidDimensions(android::util::WAKELOCK_STATE_CHANGED,
+ FieldMatcher dimensions = CreateAttributionUidDimensions(util::WAKELOCK_STATE_CHANGED,
{Position::FIRST});
*holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
*config.add_predicate() = holdingWakelockPredicate;
auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
*isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
- CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
+ CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
*config.add_predicate() = isInBackgroundPredicate;
auto durationMetric = config.add_duration_metric();
@@ -575,17 +575,17 @@
durationMetric->set_aggregation_type(DurationMetric::SUM);
// The metric is dimensioning by first attribution node and only by uid.
*durationMetric->mutable_dimensions_in_what() = CreateAttributionUidDimensions(
- android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
durationMetric->set_bucket(FIVE_MINUTES);
// Links between wakelock state atom and condition of app is in background.
auto links = durationMetric->add_links();
links->set_condition(isInBackgroundPredicate.id());
auto dimensionWhat = links->mutable_fields_in_what();
- dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
+ dimensionWhat->set_field(util::WAKELOCK_STATE_CHANGED);
dimensionWhat->add_child()->set_field(1); // uid field.
*links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
- android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
+ util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
auto metric_activation1 = config.add_metric_activation();
metric_activation1->set_metric_id(durationMetric->id());
@@ -694,7 +694,7 @@
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// Validate dimension value.
ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, appUid);
+ util::WAKELOCK_STATE_CHANGED, appUid);
// Validate bucket info.
EXPECT_EQ(2, data.bucket_info_size());
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index 594c1e6..ca4de6d 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -32,7 +32,7 @@
namespace {
const int64_t metricId = 123456;
-const int32_t ATOM_TAG = android::util::SUBSYSTEM_SLEEP_STATE;
+const int32_t ATOM_TAG = util::SUBSYSTEM_SLEEP_STATE;
StatsdConfig CreateStatsdConfig(const GaugeMetric::SamplingType sampling_type,
bool useCondition = true) {
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
index 6e3d93a..81e1c05 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
@@ -35,12 +35,12 @@
*config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
*config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
- auto atomMatcher = CreateSimpleAtomMatcher("", android::util::APP_START_OCCURRED);
+ auto atomMatcher = CreateSimpleAtomMatcher("", util::APP_START_OCCURRED);
*config.add_atom_matcher() = atomMatcher;
auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
*isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
- CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ });
+ CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ });
*config.add_predicate() = isInBackgroundPredicate;
auto gaugeMetric = config.add_gauge_metric();
@@ -50,21 +50,21 @@
gaugeMetric->mutable_gauge_fields_filter()->set_include_all(false);
gaugeMetric->set_sampling_type(sampling_type);
auto fieldMatcher = gaugeMetric->mutable_gauge_fields_filter()->mutable_fields();
- fieldMatcher->set_field(android::util::APP_START_OCCURRED);
+ fieldMatcher->set_field(util::APP_START_OCCURRED);
fieldMatcher->add_child()->set_field(3); // type (enum)
fieldMatcher->add_child()->set_field(4); // activity_name(str)
fieldMatcher->add_child()->set_field(7); // activity_start_msec(int64)
*gaugeMetric->mutable_dimensions_in_what() =
- CreateDimensions(android::util::APP_START_OCCURRED, {1 /* uid field */ });
+ CreateDimensions(util::APP_START_OCCURRED, {1 /* uid field */ });
gaugeMetric->set_bucket(FIVE_MINUTES);
auto links = gaugeMetric->add_links();
links->set_condition(isInBackgroundPredicate.id());
auto dimensionWhat = links->mutable_fields_in_what();
- dimensionWhat->set_field(android::util::APP_START_OCCURRED);
+ dimensionWhat->set_field(util::APP_START_OCCURRED);
dimensionWhat->add_child()->set_field(1); // uid field.
auto dimensionCondition = links->mutable_fields_in_condition();
- dimensionCondition->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
+ dimensionCondition->set_field(util::ACTIVITY_FOREGROUND_STATE_CHANGED);
dimensionCondition->add_child()->set_field(1); // uid field.
return config;
}
@@ -74,7 +74,7 @@
AppStartOccurred::TransitionType type, const string& activity_name,
const string& calling_pkg_name, const bool is_instant_app, int64_t activity_start_msec) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
- AStatsEvent_setAtomId(statsEvent, android::util::APP_START_OCCURRED);
+ AStatsEvent_setAtomId(statsEvent, util::APP_START_OCCURRED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, uid);
@@ -173,7 +173,7 @@
EXPECT_EQ(2, gaugeMetrics.data_size());
auto data = gaugeMetrics.data(0);
- EXPECT_EQ(android::util::APP_START_OCCURRED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::APP_START_OCCURRED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -272,7 +272,7 @@
data = gaugeMetrics.data(1);
- EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_OCCURRED);
+ EXPECT_EQ(data.dimensions_in_what().field(), util::APP_START_OCCURRED);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
diff --git a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
index 1dd90e2..f1e2744 100644
--- a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
@@ -45,7 +45,7 @@
countMetric->set_what(crashMatcher.id());
countMetric->set_bucket(FIVE_MINUTES);
countMetric->mutable_dimensions_in_what()->set_field(
- android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+ util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
countMetric->mutable_dimensions_in_what()->add_child()->set_field(1); // uid field
auto metric_activation1 = config.add_metric_activation();
@@ -79,7 +79,7 @@
countMetric->set_what(crashMatcher.id());
countMetric->set_bucket(FIVE_MINUTES);
countMetric->mutable_dimensions_in_what()->set_field(
- android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+ util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
countMetric->mutable_dimensions_in_what()->add_child()->set_field(1); // uid field
auto metric_activation1 = config.add_metric_activation();
@@ -117,7 +117,7 @@
countMetric->set_what(crashMatcher.id());
countMetric->set_bucket(FIVE_MINUTES);
countMetric->mutable_dimensions_in_what()->set_field(
- android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+ util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
countMetric->mutable_dimensions_in_what()->add_child()->set_field(1); // uid field
auto metric_activation1 = config.add_metric_activation();
@@ -153,7 +153,7 @@
countMetric->set_what(crashMatcher.id());
countMetric->set_bucket(FIVE_MINUTES);
countMetric->mutable_dimensions_in_what()->set_field(
- android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+ util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
countMetric->mutable_dimensions_in_what()->add_child()->set_field(1); // uid field
auto metric_activation1 = config.add_metric_activation();
@@ -194,7 +194,7 @@
countMetric->set_what(crashMatcher.id());
countMetric->set_bucket(FIVE_MINUTES);
countMetric->mutable_dimensions_in_what()->set_field(
- android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+ util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
countMetric->mutable_dimensions_in_what()->add_child()->set_field(1); // uid field
int64_t metricId2 = 234567;
@@ -203,7 +203,7 @@
countMetric->set_what(foregroundMatcher.id());
countMetric->set_bucket(FIVE_MINUTES);
countMetric->mutable_dimensions_in_what()->set_field(
- android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
+ util::ACTIVITY_FOREGROUND_STATE_CHANGED);
countMetric->mutable_dimensions_in_what()->add_child()->set_field(1); // uid field
auto metric_activation1 = config.add_metric_activation();
@@ -398,7 +398,7 @@
EXPECT_EQ(4, countMetrics.data_size());
auto data = countMetrics.data(0);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -409,7 +409,7 @@
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(1);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -420,7 +420,7 @@
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(2);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -433,7 +433,7 @@
data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(3);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -706,7 +706,7 @@
EXPECT_EQ(5, countMetrics.data_size());
auto data = countMetrics.data(0);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -717,7 +717,7 @@
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(1);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -728,7 +728,7 @@
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(2);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -741,7 +741,7 @@
data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(3);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -754,7 +754,7 @@
data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(4);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1040,7 +1040,7 @@
EXPECT_EQ(5, countMetrics.data_size());
auto data = countMetrics.data(0);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1051,7 +1051,7 @@
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(1);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1062,7 +1062,7 @@
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(2);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1075,7 +1075,7 @@
data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(3);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1088,7 +1088,7 @@
data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(4);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1264,7 +1264,7 @@
EXPECT_EQ(3, countMetrics.data_size());
auto data = countMetrics.data(0);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1275,7 +1275,7 @@
EXPECT_EQ(firstDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(1);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1286,7 +1286,7 @@
EXPECT_EQ(firstDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(2);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1704,7 +1704,7 @@
EXPECT_EQ(5, countMetrics.data_size());
auto data = countMetrics.data(0);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1715,7 +1715,7 @@
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(1);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1726,7 +1726,7 @@
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(2);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1739,7 +1739,7 @@
data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(3);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1752,7 +1752,7 @@
data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(4);
- EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1769,7 +1769,7 @@
EXPECT_EQ(5, countMetrics.data_size());
data = countMetrics.data(0);
- EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1780,7 +1780,7 @@
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(1);
- EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1791,7 +1791,7 @@
EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(2);
- EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1804,7 +1804,7 @@
data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(3);
- EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -1817,7 +1817,7 @@
data.bucket_info(0).end_bucket_elapsed_nanos());
data = countMetrics.data(4);
- EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+ EXPECT_EQ(util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* uid field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index e8fb523..f0df2c6 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -48,12 +48,12 @@
auto isSyncingPredicate = CreateIsSyncingPredicate();
auto syncDimension = isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions();
*syncDimension = CreateAttributionUidDimensions(
- android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ util::SYNC_STATE_CHANGED, {Position::FIRST});
syncDimension->add_child()->set_field(2 /* name field*/);
auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
*isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
- CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ });
+ CreateDimensions(util::ACTIVITY_FOREGROUND_STATE_CHANGED, {1 /* uid field */ });
*config.add_predicate() = screenIsOffPredicate;
*config.add_predicate() = isSyncingPredicate;
@@ -72,26 +72,26 @@
countMetric->set_condition(combinationPredicate->id());
// The metric is dimensioning by uid only.
*countMetric->mutable_dimensions_in_what() =
- CreateDimensions(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, {1});
+ CreateDimensions(util::PROCESS_LIFE_CYCLE_STATE_CHANGED, {1});
countMetric->set_bucket(FIVE_MINUTES);
// Links between crash atom and condition of app is in syncing.
auto links = countMetric->add_links();
links->set_condition(isSyncingPredicate.id());
auto dimensionWhat = links->mutable_fields_in_what();
- dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+ dimensionWhat->set_field(util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
dimensionWhat->add_child()->set_field(1); // uid field.
*links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
- android::util::SYNC_STATE_CHANGED, {Position::FIRST});
+ util::SYNC_STATE_CHANGED, {Position::FIRST});
// Links between crash atom and condition of app is in background.
links = countMetric->add_links();
links->set_condition(isInBackgroundPredicate.id());
dimensionWhat = links->mutable_fields_in_what();
- dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+ dimensionWhat->set_field(util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
dimensionWhat->add_child()->set_field(1); // uid field.
auto dimensionCondition = links->mutable_fields_in_condition();
- dimensionCondition->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
+ dimensionCondition->set_field(util::ACTIVITY_FOREGROUND_STATE_CHANGED);
dimensionCondition->add_child()->set_field(1); // uid field.
return config;
}
@@ -211,7 +211,7 @@
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
auto data = reports.reports(0).metrics(0).count_metrics().data(0);
// Validate dimension value.
- EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().field(), util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
// Uid field.
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
@@ -332,7 +332,7 @@
EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
auto data = reports.reports(0).metrics(0).count_metrics().data(0);
// Validate dimension value.
- EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+ EXPECT_EQ(data.dimensions_in_what().field(), util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
// Uid field.
EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index b975907..371a346 100644
--- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -73,7 +73,7 @@
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
auto pulledAtomMatcher =
- CreateSimpleAtomMatcher("TestMatcher", android::util::SUBSYSTEM_SLEEP_STATE);
+ CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
*config.add_atom_matcher() = pulledAtomMatcher;
*config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
*config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
@@ -82,9 +82,9 @@
valueMetric->set_id(123456);
valueMetric->set_what(pulledAtomMatcher.id());
*valueMetric->mutable_value_field() =
- CreateDimensions(android::util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
+ CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
*valueMetric->mutable_dimensions_in_what() =
- CreateDimensions(android::util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
+ CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
valueMetric->set_bucket(FIVE_MINUTES);
valueMetric->set_min_bucket_size_nanos(minTime);
valueMetric->set_use_absolute_value_on_reset(true);
@@ -96,7 +96,7 @@
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
auto pulledAtomMatcher =
- CreateSimpleAtomMatcher("TestMatcher", android::util::SUBSYSTEM_SLEEP_STATE);
+ CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
*config.add_atom_matcher() = pulledAtomMatcher;
*config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
*config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
@@ -106,7 +106,7 @@
gaugeMetric->set_what(pulledAtomMatcher.id());
gaugeMetric->mutable_gauge_fields_filter()->set_include_all(true);
*gaugeMetric->mutable_dimensions_in_what() =
- CreateDimensions(android::util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
+ CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
gaugeMetric->set_bucket(FIVE_MINUTES);
gaugeMetric->set_min_bucket_size_nanos(minTime);
return config;
@@ -218,7 +218,7 @@
TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
service->mPullerManager->RegisterPullAtomCallback(
- /*uid=*/0, android::util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
+ /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
SharedRefBase::make<FakeSubsystemSleepCallback>());
// Partial buckets don't occur when app is first installed.
service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
@@ -239,7 +239,7 @@
TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
service->mPullerManager->RegisterPullAtomCallback(
- /*uid=*/0, android::util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
+ /*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
SharedRefBase::make<FakeSubsystemSleepCallback>());
// Partial buckets don't occur when app is first installed.
service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index a87bb71..a5ef733 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -37,7 +37,7 @@
StatsdConfig config;
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
auto pulledAtomMatcher =
- CreateSimpleAtomMatcher("TestMatcher", android::util::SUBSYSTEM_SLEEP_STATE);
+ CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
*config.add_atom_matcher() = pulledAtomMatcher;
*config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
*config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
@@ -52,9 +52,9 @@
valueMetric->set_condition(screenIsOffPredicate.id());
}
*valueMetric->mutable_value_field() =
- CreateDimensions(android::util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
+ CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
*valueMetric->mutable_dimensions_in_what() =
- CreateDimensions(android::util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
+ CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {1 /* subsystem name */});
valueMetric->set_bucket(FIVE_MINUTES);
valueMetric->set_use_absolute_value_on_reset(true);
valueMetric->set_skip_zero_diff_output(false);
@@ -73,7 +73,7 @@
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(),
- android::util::SUBSYSTEM_SLEEP_STATE);
+ util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
@@ -142,7 +142,7 @@
EXPECT_GT((int)valueMetrics.data_size(), 1);
auto data = valueMetrics.data(0);
- EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
+ EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -177,7 +177,7 @@
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(),
- android::util::SUBSYSTEM_SLEEP_STATE);
+ util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
@@ -250,7 +250,7 @@
EXPECT_GT((int)valueMetrics.data_size(), 1);
auto data = valueMetrics.data(0);
- EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
+ EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -289,7 +289,7 @@
ConfigKey cfgKey;
auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
SharedRefBase::make<FakeSubsystemSleepCallback>(),
- android::util::SUBSYSTEM_SLEEP_STATE);
+ util::SUBSYSTEM_SLEEP_STATE);
EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
processor->mPullerManager->ForceClearPullerCache();
@@ -353,7 +353,7 @@
EXPECT_GT((int)valueMetrics.data_size(), 0);
auto data = valueMetrics.data(0);
- EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
+ EXPECT_EQ(util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
EXPECT_EQ(1 /* subsystem name field */,
data.dimensions_in_what().value_tuple().dimensions_value(0).field());
@@ -383,7 +383,7 @@
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
auto pulledAtomMatcher =
- CreateSimpleAtomMatcher("TestMatcher", android::util::SUBSYSTEM_SLEEP_STATE);
+ CreateSimpleAtomMatcher("TestMatcher", util::SUBSYSTEM_SLEEP_STATE);
*config.add_atom_matcher() = pulledAtomMatcher;
auto screenState = CreateScreenState();
@@ -396,7 +396,7 @@
valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
valueMetric->set_what(pulledAtomMatcher.id());
*valueMetric->mutable_value_field() =
- CreateDimensions(android::util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
+ CreateDimensions(util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
valueMetric->add_slice_by_state(screenState.id());
valueMetric->set_max_pull_delay_sec(INT_MAX);
@@ -437,7 +437,7 @@
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
auto cpuTimePerUidMatcher =
- CreateSimpleAtomMatcher("CpuTimePerUidMatcher", android::util::CPU_TIME_PER_UID);
+ CreateSimpleAtomMatcher("CpuTimePerUidMatcher", util::CPU_TIME_PER_UID);
*config.add_atom_matcher() = cpuTimePerUidMatcher;
auto uidProcessState = CreateUidProcessState();
@@ -450,14 +450,14 @@
valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
valueMetric->set_what(cpuTimePerUidMatcher.id());
*valueMetric->mutable_value_field() =
- CreateDimensions(android::util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
+ CreateDimensions(util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
*valueMetric->mutable_dimensions_in_what() =
- CreateDimensions(android::util::CPU_TIME_PER_UID, {1 /* uid */});
+ CreateDimensions(util::CPU_TIME_PER_UID, {1 /* uid */});
valueMetric->add_slice_by_state(uidProcessState.id());
MetricStateLink* stateLink = valueMetric->add_state_link();
stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
auto fieldsInWhat = stateLink->mutable_fields_in_what();
- *fieldsInWhat = CreateDimensions(android::util::CPU_TIME_PER_UID, {1 /* uid */});
+ *fieldsInWhat = CreateDimensions(util::CPU_TIME_PER_UID, {1 /* uid */});
auto fieldsInState = stateLink->mutable_fields_in_state();
*fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
valueMetric->set_max_pull_delay_sec(INT_MAX);
@@ -497,7 +497,7 @@
config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
auto cpuTimePerUidMatcher =
- CreateSimpleAtomMatcher("CpuTimePerUidMatcher", android::util::CPU_TIME_PER_UID);
+ CreateSimpleAtomMatcher("CpuTimePerUidMatcher", util::CPU_TIME_PER_UID);
*config.add_atom_matcher() = cpuTimePerUidMatcher;
auto uidProcessState = CreateUidProcessState();
@@ -510,12 +510,12 @@
valueMetric->set_bucket(TimeUnit::FIVE_MINUTES);
valueMetric->set_what(cpuTimePerUidMatcher.id());
*valueMetric->mutable_value_field() =
- CreateDimensions(android::util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
+ CreateDimensions(util::CPU_TIME_PER_UID, {2 /* user_time_micros */});
valueMetric->add_slice_by_state(uidProcessState.id());
MetricStateLink* stateLink = valueMetric->add_state_link();
stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
auto fieldsInWhat = stateLink->mutable_fields_in_what();
- *fieldsInWhat = CreateDimensions(android::util::CPU_TIME_PER_UID, {1 /* uid */});
+ *fieldsInWhat = CreateDimensions(util::CPU_TIME_PER_UID, {1 /* uid */});
auto fieldsInState = stateLink->mutable_fields_in_state();
*fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
valueMetric->set_max_pull_delay_sec(INT_MAX);
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index ddd8f95..80f3c28 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -42,7 +42,7 @@
auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
// The predicate is dimensioning by any attribution node and both by uid and tag.
FieldMatcher dimensions = CreateAttributionUidAndTagDimensions(
- android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST, Position::LAST});
+ util::WAKELOCK_STATE_CHANGED, {Position::FIRST, Position::LAST});
// Also slice by the wakelock tag
dimensions.add_child()->set_field(3); // The wakelock tag is set in field 3 of the wakelock.
*holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
@@ -56,7 +56,7 @@
// The metric is dimensioning by first attribution node and only by uid.
*durationMetric->mutable_dimensions_in_what() =
CreateAttributionUidDimensions(
- android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+ util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
durationMetric->set_bucket(FIVE_MINUTES);
return config;
}
@@ -142,7 +142,7 @@
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// Validate dimension value.
ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 111);
+ util::WAKELOCK_STATE_CHANGED, 111);
// Validate bucket info.
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
data = reports.reports(0).metrics(0).duration_metrics().data(0);
@@ -178,7 +178,7 @@
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// Validate dimension value.
ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 111);
+ util::WAKELOCK_STATE_CHANGED, 111);
// Two output buckets.
// The wakelock holding interval in the 1st bucket starts from the screen off event and to
// the end of the 1st bucket.
@@ -228,7 +228,7 @@
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 6);
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 111);
+ util::WAKELOCK_STATE_CHANGED, 111);
// The last wakelock holding spans 4 buckets.
EXPECT_EQ((unsigned long long)data.bucket_info(2).duration_nanos(), bucketSizeNs - 100);
EXPECT_EQ((unsigned long long)data.bucket_info(3).duration_nanos(), bucketSizeNs);
@@ -293,7 +293,7 @@
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
// Validate dimension value.
ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 111);
+ util::WAKELOCK_STATE_CHANGED, 111);
// The max is acquire event for wl1 to screen off start.
EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs + 2 - 200);
}
@@ -337,7 +337,7 @@
EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
ValidateAttributionUidDimension(data.dimensions_in_what(),
- android::util::WAKELOCK_STATE_CHANGED, 111);
+ util::WAKELOCK_STATE_CHANGED, 111);
// The last wakelock holding spans 4 buckets.
EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 3 * bucketSizeNs);
EXPECT_EQ((unsigned long long)data.bucket_info(1).start_bucket_elapsed_nanos(),
diff --git a/cmds/statsd/tests/external/puller_util_test.cpp b/cmds/statsd/tests/external/puller_util_test.cpp
index f21954f2..15425d8 100644
--- a/cmds/statsd/tests/external/puller_util_test.cpp
+++ b/cmds/statsd/tests/external/puller_util_test.cpp
@@ -22,7 +22,7 @@
#include "../metrics/metrics_test_helper.h"
#include "stats_event.h"
-#include "statslog.h"
+#include "statslog_statsdtest.h"
#ifdef __ANDROID__
@@ -39,9 +39,9 @@
* Test merge isolated and host uid
*/
namespace {
-int uidAtomTagId = android::util::CPU_CLUSTER_TIME;
+int uidAtomTagId = util::CPU_CLUSTER_TIME;
const vector<int> uidAdditiveFields = {3};
-int nonUidAtomTagId = android::util::SYSTEM_UPTIME;
+int nonUidAtomTagId = util::SYSTEM_UPTIME;
int timestamp = 1234;
int isolatedUid = 30;
int isolatedAdditiveData = 31;
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index 2a43d9b..00e8397 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -13,7 +13,7 @@
// limitations under the License.
#include "src/guardrail/StatsdStats.h"
-#include "statslog.h"
+#include "statslog_statsdtest.h"
#include "tests/statsd_test_util.h"
#include <gtest/gtest.h>
@@ -222,11 +222,11 @@
StatsdStats stats;
time_t now = time(nullptr);
// old event, we get it from the stats buffer. should be ignored.
- stats.noteAtomLogged(android::util::SENSOR_STATE_CHANGED, 1000);
+ stats.noteAtomLogged(util::SENSOR_STATE_CHANGED, 1000);
- stats.noteAtomLogged(android::util::SENSOR_STATE_CHANGED, now + 1);
- stats.noteAtomLogged(android::util::SENSOR_STATE_CHANGED, now + 2);
- stats.noteAtomLogged(android::util::APP_CRASH_OCCURRED, now + 3);
+ stats.noteAtomLogged(util::SENSOR_STATE_CHANGED, now + 1);
+ stats.noteAtomLogged(util::SENSOR_STATE_CHANGED, now + 2);
+ stats.noteAtomLogged(util::APP_CRASH_OCCURRED, now + 3);
vector<uint8_t> output;
stats.dumpStats(&output, false);
@@ -239,10 +239,10 @@
bool dropboxAtomGood = false;
for (const auto& atomStats : report.atom_stats()) {
- if (atomStats.tag() == android::util::SENSOR_STATE_CHANGED && atomStats.count() == 3) {
+ if (atomStats.tag() == util::SENSOR_STATE_CHANGED && atomStats.count() == 3) {
sensorAtomGood = true;
}
- if (atomStats.tag() == android::util::APP_CRASH_OCCURRED && atomStats.count() == 1) {
+ if (atomStats.tag() == util::APP_CRASH_OCCURRED && atomStats.count() == 1) {
dropboxAtomGood = true;
}
}
@@ -287,21 +287,21 @@
TEST(StatsdStatsTest, TestPullAtomStats) {
StatsdStats stats;
- stats.updateMinPullIntervalSec(android::util::DISK_SPACE, 3333L);
- stats.updateMinPullIntervalSec(android::util::DISK_SPACE, 2222L);
- stats.updateMinPullIntervalSec(android::util::DISK_SPACE, 4444L);
+ stats.updateMinPullIntervalSec(util::DISK_SPACE, 3333L);
+ stats.updateMinPullIntervalSec(util::DISK_SPACE, 2222L);
+ stats.updateMinPullIntervalSec(util::DISK_SPACE, 4444L);
- stats.notePull(android::util::DISK_SPACE);
- stats.notePullTime(android::util::DISK_SPACE, 1111L);
- stats.notePullDelay(android::util::DISK_SPACE, 1111L);
- stats.notePull(android::util::DISK_SPACE);
- stats.notePullTime(android::util::DISK_SPACE, 3333L);
- stats.notePullDelay(android::util::DISK_SPACE, 3335L);
- stats.notePull(android::util::DISK_SPACE);
- stats.notePullFromCache(android::util::DISK_SPACE);
- stats.notePullerCallbackRegistrationChanged(android::util::DISK_SPACE, true);
- stats.notePullerCallbackRegistrationChanged(android::util::DISK_SPACE, false);
- stats.notePullerCallbackRegistrationChanged(android::util::DISK_SPACE, true);
+ stats.notePull(util::DISK_SPACE);
+ stats.notePullTime(util::DISK_SPACE, 1111L);
+ stats.notePullDelay(util::DISK_SPACE, 1111L);
+ stats.notePull(util::DISK_SPACE);
+ stats.notePullTime(util::DISK_SPACE, 3333L);
+ stats.notePullDelay(util::DISK_SPACE, 3335L);
+ stats.notePull(util::DISK_SPACE);
+ stats.notePullFromCache(util::DISK_SPACE);
+ stats.notePullerCallbackRegistrationChanged(util::DISK_SPACE, true);
+ stats.notePullerCallbackRegistrationChanged(util::DISK_SPACE, false);
+ stats.notePullerCallbackRegistrationChanged(util::DISK_SPACE, true);
vector<uint8_t> output;
@@ -312,7 +312,7 @@
EXPECT_EQ(1, report.pulled_atom_stats_size());
- EXPECT_EQ(android::util::DISK_SPACE, report.pulled_atom_stats(0).atom_id());
+ EXPECT_EQ(util::DISK_SPACE, report.pulled_atom_stats(0).atom_id());
EXPECT_EQ(3, report.pulled_atom_stats(0).total_pull());
EXPECT_EQ(1, report.pulled_atom_stats(0).total_pull_from_cache());
EXPECT_EQ(2222L, report.pulled_atom_stats(0).min_pull_interval_sec());
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index e48f378..fab8e68 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -79,1615 +79,1417 @@
}
}
-// TODO(b/149590301): Update these tests to use new socket schema.
-//class ValueMetricProducerTestHelper {
-//
-// public:
-// static shared_ptr<LogEvent> createEvent(int64_t eventTimeNs, int64_t value) {
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventTimeNs);
-// event->write(tagId);
-// event->write(value);
-// event->write(value);
-// event->init();
-// return event;
-// }
-//
-// static sp<ValueMetricProducer> createValueProducerNoConditions(
-// sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-//
-// sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
-// kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-// logEventMatcherIndex, eventMatcherWizard, tagId,
-// bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-// return valueProducer;
-// }
-//
-// static sp<ValueMetricProducer> createValueProducerWithCondition(
-// sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-//
-// sp<ValueMetricProducer> valueProducer =
-// new ValueMetricProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, tagId, bucketStartTimeNs,
-// bucketStartTimeNs, pullerManager);
-// valueProducer->mCondition = ConditionState::kFalse;
-// return valueProducer;
-// }
-//
-// static sp<ValueMetricProducer> createValueProducerWithNoInitialCondition(
-// sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-//
-// sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
-// kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
-// bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-// return valueProducer;
-// }
-//
-// static sp<ValueMetricProducer> createValueProducerWithState(
-// sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
-// vector<int32_t> slicedStateAtoms,
-// unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) {
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-// sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
-// kConfigKey, metric, -1 /* no condition */, wizard, logEventMatcherIndex,
-// eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
-// {}, slicedStateAtoms, stateGroupMap);
-// return valueProducer;
-// }
-//
-// static ValueMetric createMetric() {
-// ValueMetric metric;
-// metric.set_id(metricId);
-// metric.set_bucket(ONE_MINUTE);
-// metric.mutable_value_field()->set_field(tagId);
-// metric.mutable_value_field()->add_child()->set_field(2);
-// metric.set_max_pull_delay_sec(INT_MAX);
-// return metric;
-// }
-//
-// static ValueMetric createMetricWithCondition() {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// metric.set_condition(StringToId("SCREEN_ON"));
-// return metric;
-// }
-//
-// static ValueMetric createMetricWithState(string state) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// metric.add_slice_by_state(StringToId(state));
-// return metric;
-// }
-//};
-//
-///*
-// * Tests that the first bucket works correctly
-// */
-//TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// int64_t startTimeBase = 11;
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-//
-// // statsd started long ago.
-// // The metric starts in the middle of the bucket
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-// logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase,
-// 22, pullerManager);
-//
-// EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
-// EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
-// EXPECT_EQ(60 * NS_PER_SEC + startTimeBase,
-// valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC));
-// EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase,
-// valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC));
-//}
-//
-///*
-// * Tests that the first bucket works correctly
-// */
-//TEST(ValueMetricProducerTest, TestFirstBucket) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-//
-// // statsd started long ago.
-// // The metric starts in the middle of the bucket
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-// logEventMatcherIndex, eventMatcherWizard, -1, 5,
-// 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
-//
-// EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
-// EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
-// EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs());
-//}
-//
-///*
-// * Tests pulled atoms with no conditions
-// */
-//TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-// event->write(tagId);
-// event->write(3);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-// event->write(tagId);
-// event->write(11);
-// event->init();
-// allData.push_back(event);
-//
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval =
-// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-//
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(11, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(8, curInterval.value.long_value);
-// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-// EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-//
-// allData.clear();
-// event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-// event->write(tagId);
-// event->write(23);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-//
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(23, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(12, curInterval.value.long_value);
-// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-// EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
-// EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-// EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
-//
-// allData.clear();
-// event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
-// event->write(tagId);
-// event->write(36);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-//
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(36, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(13, curInterval.value.long_value);
-// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-// EXPECT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
-// EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-// EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
-// EXPECT_EQ(13, valueProducer->mPastBuckets.begin()->second[2].values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[2].mConditionTrueNs);
-//}
-//
-//TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // Initialize bucket.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-// event->write(tagId);
-// event->write(1);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// // Partial bucket.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
-// event->write(tagId);
-// event->write(5);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-//
-// // First bucket ends.
-// vector<shared_ptr<LogEvent>> allData;
-// allData.clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
-// event->write(tagId);
-// event->write(2);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
-//
-// // Partial buckets created in 2nd bucket.
-// valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
-//
-// // One full bucket and one partial bucket.
-// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-// vector<ValueBucket> buckets = valueProducer->mPastBuckets.begin()->second;
-// EXPECT_EQ(2UL, buckets.size());
-// // Full bucket (2 - 1)
-// EXPECT_EQ(1, buckets[0].values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, buckets[0].mConditionTrueNs);
-// // Full bucket (5 - 3)
-// EXPECT_EQ(3, buckets[1].values[0].long_value);
-// // partial bucket [bucket2StartTimeNs, bucket2StartTimeNs + 2]
-// EXPECT_EQ(2, buckets[1].mConditionTrueNs);
-//}
-//
-///*
-// * Tests pulled atoms with filtering
-// */
-//TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// auto keyValue = atomMatcher.add_field_value_matcher();
-// keyValue->set_field(1);
-// keyValue->set_eq_int(3);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-// event->write(3);
-// event->write(3);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
-// kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
-// eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-// event->write(3);
-// event->write(11);
-// event->init();
-// allData.push_back(event);
-//
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval =
-// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-//
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(11, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(8, curInterval.value.long_value);
-// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-// EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-//
-// allData.clear();
-// event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-// event->write(4);
-// event->write(23);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-// // No new data seen, so data has been cleared.
-// EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-//
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(11, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(8, curInterval.value.long_value);
-// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-// EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-//
-// allData.clear();
-// event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
-// event->write(3);
-// event->write(36);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-//
-// // the base was reset
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(36, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-// EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
-// EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
-//}
-//
-///*
-// * Tests pulled atoms with no conditions and take absolute value after reset
-// */
-//TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// metric.set_use_absolute_value_on_reset(true);
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-// event->write(tagId);
-// event->write(11);
-// event->init();
-// allData.push_back(event);
-//
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-//
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(11, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-//
-// allData.clear();
-// event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-// event->write(tagId);
-// event->write(10);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(10, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(10, curInterval.value.long_value);
-// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-// EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
-//
-// allData.clear();
-// event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
-// event->write(tagId);
-// event->write(36);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(36, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(26, curInterval.value.long_value);
-// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-// EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
-// EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-// EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
-//}
-//
-///*
-// * Tests pulled atoms with no conditions and take zero value after reset
-// */
-//TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-// event->write(tagId);
-// event->write(11);
-// event->init();
-// allData.push_back(event);
-//
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-//
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(11, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-//
-// allData.clear();
-// event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-// event->write(tagId);
-// event->write(10);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(10, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-//
-// allData.clear();
-// event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
-// event->write(tagId);
-// event->write(36);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(36, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(26, curInterval.value.long_value);
-// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-// EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-// EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-//}
-//
-///*
-// * Test pulled event with non sliced condition.
-// */
-//TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-//
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-// event->write(tagId);
-// event->write(100);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-// event->write(tagId);
-// event->write(130);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-// event->write(tagId);
-// event->write(180);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-//
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// // startUpdated:false sum:0 start:100
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(100, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-// event->write(1);
-// event->write(110);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(110, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(10, curInterval.value.long_value);
-//
-// valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curInterval.hasValue);
-// EXPECT_EQ(20, curInterval.value.long_value);
-// EXPECT_EQ(false, curBaseInfo.hasBase);
-//
-// valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1);
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1});
-//}
-//
-//TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-// pullerManager);
-//
-// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-// event1->write(1);
-// event1->write(10);
-// event1->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-//
-// valueProducer.notifyAppUpgrade(bucketStartTimeNs + 150, "ANY.APP", 1, 1);
-// EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-// EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
-//
-// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
-// event2->write(1);
-// event2->write(10);
-// event2->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-// EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-// EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
-//
-// // Next value should create a new bucket.
-// shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
-// event3->write(1);
-// event3->write(10);
-// event3->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
-// EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-// EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
-//}
-//
-//TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// .WillOnce(Return(true))
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 149);
-// event->write(tagId);
-// event->write(120);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, tagId, bucketStartTimeNs,
-// bucketStartTimeNs, pullerManager);
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-// event->write(tagId);
-// event->write(100);
-// event->init();
-// allData.push_back(event);
-//
-// valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-//
-// valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
-// EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-// EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
-// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {150});
-//
-// allData.clear();
-// event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-// event->write(tagId);
-// event->write(150);
-// event->init();
-// allData.push_back(event);
-// valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-// EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-// EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
-// EXPECT_EQ(20L,
-// valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
-// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20, 30},
-// {150, bucketSizeNs - 150});
-//}
-//
-//TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// metric.set_split_bucket_for_app_upgrade(false);
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-// EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, tagId, bucketStartTimeNs,
-// bucketStartTimeNs, pullerManager);
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-// event->write(tagId);
-// event->write(100);
-// event->init();
-// allData.push_back(event);
-//
-// valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-//
-// valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
-// EXPECT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-// EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
-//}
-//
-//TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-// event->write(tagId);
-// event->write(100);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
-// event->write(tagId);
-// event->write(120);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-//
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
-//
-// valueProducer->onConditionChanged(false, bucket2StartTimeNs-100);
-// EXPECT_FALSE(valueProducer->mCondition);
-//
-// valueProducer->notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
-// // Expect one full buckets already done and starting a partial bucket.
-// EXPECT_EQ(bucket2StartTimeNs-50, valueProducer->mCurrentBucketStartTimeNs);
-// EXPECT_EQ(1UL, valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-// EXPECT_EQ(bucketStartTimeNs,
-// valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20},
-// {(bucket2StartTimeNs - 100) - (bucketStartTimeNs + 1)});
-// EXPECT_FALSE(valueProducer->mCondition);
-//}
-//
-//TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-//
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-// pullerManager);
-//
-// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-// event1->write(1);
-// event1->write(10);
-// event1->init();
-// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-// event2->write(1);
-// event2->write(20);
-// event2->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(10, curInterval.value.long_value);
-// EXPECT_EQ(true, curInterval.hasValue);
-//
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// EXPECT_EQ(30, curInterval.value.long_value);
-//
-// valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
-// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {30}, {bucketSizeNs});
-//}
-//
-//TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-//
-// ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-// pullerManager);
-// valueProducer.mCondition = ConditionState::kFalse;
-//
-// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-// event1->write(1);
-// event1->write(10);
-// event1->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-// // has 1 slice
-// EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
-//
-// valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
-// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-// event2->write(1);
-// event2->write(20);
-// event2->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval =
-// valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// EXPECT_EQ(20, curInterval.value.long_value);
-//
-// shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 30);
-// event3->write(1);
-// event3->write(30);
-// event3->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// EXPECT_EQ(50, curInterval.value.long_value);
-//
-// valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
-// shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
-// event4->write(1);
-// event4->write(40);
-// event4->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// EXPECT_EQ(50, curInterval.value.long_value);
-//
-// valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
-// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {50}, {20});
-//}
-//
-//TEST(ValueMetricProducerTest, TestAnomalyDetection) {
-// sp<AlarmMonitor> alarmMonitor;
-// Alert alert;
-// alert.set_id(101);
-// alert.set_metric_id(metricId);
-// alert.set_trigger_if_sum_gt(130);
-// alert.set_num_buckets(2);
-// const int32_t refPeriodSec = 3;
-// alert.set_refractory_period_secs(refPeriodSec);
-//
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-// logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
-// bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-//
-// sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
-//
-//
-// shared_ptr<LogEvent> event1
-// = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
-// event1->write(161);
-// event1->write(10); // value of interest
-// event1->init();
-// shared_ptr<LogEvent> event2
-// = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
-// event2->write(162);
-// event2->write(20); // value of interest
-// event2->init();
-// shared_ptr<LogEvent> event3
-// = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
-// event3->write(163);
-// event3->write(130); // value of interest
-// event3->init();
-// shared_ptr<LogEvent> event4
-// = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
-// event4->write(35);
-// event4->write(1); // value of interest
-// event4->init();
-// shared_ptr<LogEvent> event5
-// = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
-// event5->write(45);
-// event5->write(150); // value of interest
-// event5->init();
-// shared_ptr<LogEvent> event6
-// = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
-// event6->write(25);
-// event6->write(160); // value of interest
-// event6->init();
-//
-// // Two events in bucket #0.
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-// // Value sum == 30 <= 130.
-// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
-//
-// // One event in bucket #2. No alarm as bucket #0 is trashed out.
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
-// // Value sum == 130 <= 130.
-// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
-//
-// // Three events in bucket #3.
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
-// // Anomaly at event 4 since Value sum == 131 > 130!
-// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-// std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
-// // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
-// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-// std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-//
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
-// // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
-// EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-// std::ceil(1.0 * event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-//}
-//
-//// Test value metric no condition, the pull on bucket boundary come in time and too late
-//TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-//
-// vector<shared_ptr<LogEvent>> allData;
-// // pull 1
-// allData.clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-// event->write(tagId);
-// event->write(11);
-// event->init();
-// allData.push_back(event);
-//
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval =
-// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-//
-// // startUpdated:true sum:0 start:11
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(11, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-//
-// // pull 2 at correct time
-// allData.clear();
-// event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-// event->write(tagId);
-// event->write(23);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// // tartUpdated:false sum:12
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(23, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
-//
-// // pull 3 come late.
-// // The previous bucket gets closed with error. (Has start value 23, no ending)
-// // Another bucket gets closed with error. (No start, but ending with 36)
-// // The new bucket is back to normal.
-// allData.clear();
-// event = make_shared<LogEvent>(tagId, bucket6StartTimeNs + 1);
-// event->write(tagId);
-// event->write(36);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// // startUpdated:false sum:12
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(36, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
-//}
-//
-///*
-// * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
-// * was delivered late.
-// */
-//TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // condition becomes true
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-// event->write(tagId);
-// event->write(100);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// // condition becomes false
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-// event->write(tagId);
-// event->write(120);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-//
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval =
-// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(100, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-//
-// // pull on bucket boundary come late, condition change happens before it
-// valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
-// EXPECT_EQ(false, curBaseInfo.hasBase);
-//
-// // Now the alarm is delivered.
-// // since the condition turned to off before this pull finish, it has no effect
-// vector<shared_ptr<LogEvent>> allData;
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-//
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(false, curBaseInfo.hasBase);
-// EXPECT_EQ(false, curInterval.hasValue);
-//}
-//
-///*
-// * Test pulled event with non sliced condition. The pull on boundary come late, after the condition
-// * change to false, and then true again. This is due to alarm delivered late.
-// */
-//TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // condition becomes true
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-// event->write(tagId);
-// event->write(100);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// // condition becomes false
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-// event->write(tagId);
-// event->write(120);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// // condition becomes true again
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 25);
-// event->write(tagId);
-// event->write(130);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-//
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval =
-// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// // startUpdated:false sum:0 start:100
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(100, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-//
-// // pull on bucket boundary come late, condition change happens before it
-// valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(false, curBaseInfo.hasBase);
-// EXPECT_EQ(false, curInterval.hasValue);
-//
-// // condition changed to true again, before the pull alarm is delivered
-// valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(130, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-//
-// // Now the alarm is delivered, but it is considered late, the data will be used
-// // for the new bucket since it was just pulled.
-// vector<shared_ptr<LogEvent>> allData;
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 50, 140));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
-//
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(140, curBaseInfo.base.long_value);
-// EXPECT_EQ(true, curInterval.hasValue);
-// EXPECT_EQ(10, curInterval.value.long_value);
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
-//
-// allData.clear();
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 160));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20, 30},
-// {bucketSizeNs - 8, bucketSizeNs - 24});
-//}
-//
-//TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// metric.set_aggregation_type(ValueMetric::MIN);
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-//
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-// pullerManager);
-//
-// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-// event1->write(1);
-// event1->write(10);
-// event1->init();
-// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-// event2->write(1);
-// event2->write(20);
-// event2->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval =
-// valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// EXPECT_EQ(10, curInterval.value.long_value);
-// EXPECT_EQ(true, curInterval.hasValue);
-//
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// EXPECT_EQ(10, curInterval.value.long_value);
-//
-// valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
-// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10}, {bucketSizeNs});
-//}
-//
-//TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// metric.set_aggregation_type(ValueMetric::MAX);
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-//
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-// pullerManager);
-//
-// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-// event1->write(1);
-// event1->write(10);
-// event1->init();
-// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-// event2->write(1);
-// event2->write(20);
-// event2->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval =
-// valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// EXPECT_EQ(10, curInterval.value.long_value);
-// EXPECT_EQ(true, curInterval.hasValue);
-//
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// EXPECT_EQ(20, curInterval.value.long_value);
-//
-// valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
-// /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); */
-// /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); */
-// /* EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); */
-//}
-//
-//TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// metric.set_aggregation_type(ValueMetric::AVG);
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-//
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-// pullerManager);
-//
-// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-// event1->write(1);
-// event1->write(10);
-// event1->init();
-// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-// event2->write(1);
-// event2->write(15);
-// event2->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval;
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// EXPECT_EQ(10, curInterval.value.long_value);
-// EXPECT_EQ(true, curInterval.hasValue);
-// EXPECT_EQ(1, curInterval.sampleSize);
-//
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// EXPECT_EQ(25, curInterval.value.long_value);
-// EXPECT_EQ(2, curInterval.sampleSize);
-//
-// valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
-// EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-// EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-//
-// EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value -
-// 12.5) < epsilon);
-//}
-//
-//TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// metric.set_aggregation_type(ValueMetric::SUM);
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-//
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-// pullerManager);
-//
-// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-// event1->write(1);
-// event1->write(10);
-// event1->init();
-// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-// event2->write(1);
-// event2->write(15);
-// event2->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval =
-// valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// EXPECT_EQ(10, curInterval.value.long_value);
-// EXPECT_EQ(true, curInterval.hasValue);
-//
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// EXPECT_EQ(25, curInterval.value.long_value);
-//
-// valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
-// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {25}, {bucketSizeNs});
-//}
-//
-//TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// metric.set_aggregation_type(ValueMetric::MIN);
-// metric.set_use_diff(true);
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-//
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-// pullerManager);
-//
-// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-// event1->write(1);
-// event1->write(10);
-// event1->init();
-// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
-// event2->write(1);
-// event2->write(15);
-// event2->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval =
-// valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(10, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-//
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// EXPECT_EQ(true, curInterval.hasValue);
-// EXPECT_EQ(5, curInterval.value.long_value);
-//
-// // no change in data.
-// shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
-// event3->write(1);
-// event3->write(15);
-// event3->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(15, curBaseInfo.base.long_value);
-// EXPECT_EQ(true, curInterval.hasValue);
-//
-// shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
-// event4->write(1);
-// event4->write(15);
-// event4->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(15, curBaseInfo.base.long_value);
-// EXPECT_EQ(true, curInterval.hasValue);
-//
-// valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
-// EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-// EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-// assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {5}, {bucketSizeNs});
-//}
-//
-//TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// metric.mutable_value_field()->add_child()->set_field(3);
-// metric.set_aggregation_type(ValueMetric::MIN);
-// metric.set_use_diff(true);
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-//
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-// pullerManager);
-//
-// shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-// event1->write(1);
-// event1->write(10);
-// event1->write(20);
-// event1->init();
-// shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
-// event2->write(1);
-// event2->write(15);
-// event2->write(22);
-// event2->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval =
-// valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(10, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(20, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-//
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-//
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curInterval.hasValue);
-// EXPECT_EQ(5, curInterval.value.long_value);
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
-// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
-// EXPECT_EQ(true, curInterval.hasValue);
-// EXPECT_EQ(2, curInterval.value.long_value);
-//
-// // no change in first value field
-// shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
-// event3->write(1);
-// event3->write(15);
-// event3->write(25);
-// event3->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-//
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(15, curBaseInfo.base.long_value);
-// EXPECT_EQ(true, curInterval.hasValue);
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
-// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(25, curBaseInfo.base.long_value);
-// EXPECT_EQ(true, curInterval.hasValue);
-//
-// shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
-// event4->write(1);
-// event4->write(15);
-// event4->write(29);
-// event4->init();
-// valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
-// EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(15, curBaseInfo.base.long_value);
-// EXPECT_EQ(true, curInterval.hasValue);
-// curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
-// curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(29, curBaseInfo.base.long_value);
-// EXPECT_EQ(true, curInterval.hasValue);
-//
-// valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
-//
-// EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-// EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
-// EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second[0].values.size());
-// EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second[1].values.size());
-//
-// EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[0].mConditionTrueNs);
-// EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
-// EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second[0].valueIndex[0]);
-// EXPECT_EQ(2, valueProducer.mPastBuckets.begin()->second[0].values[1].long_value);
-// EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].valueIndex[1]);
-//
-// EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[1].mConditionTrueNs);
-// EXPECT_EQ(3, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
-// EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[1].valueIndex[0]);
-//}
-//
+class ValueMetricProducerTestHelper {
+public:
+ static sp<ValueMetricProducer> createValueProducerNoConditions(
+ sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+ kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ return valueProducer;
+ }
+
+ static sp<ValueMetricProducer> createValueProducerWithCondition(
+ sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+ kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ valueProducer->mCondition = ConditionState::kFalse;
+ return valueProducer;
+ }
+
+ static sp<ValueMetricProducer> createValueProducerWithNoInitialCondition(
+ sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+ kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ return valueProducer;
+ }
+
+ static sp<ValueMetricProducer> createValueProducerWithState(
+ sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
+ vector<int32_t> slicedStateAtoms,
+ unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) {
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+ sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+ kConfigKey, metric, -1 /* no condition */, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
+ {}, slicedStateAtoms, stateGroupMap);
+ return valueProducer;
+ }
+
+ static ValueMetric createMetric() {
+ ValueMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ metric.mutable_value_field()->set_field(tagId);
+ metric.mutable_value_field()->add_child()->set_field(2);
+ metric.set_max_pull_delay_sec(INT_MAX);
+ return metric;
+ }
+
+ static ValueMetric createMetricWithCondition() {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.set_condition(StringToId("SCREEN_ON"));
+ return metric;
+ }
+
+ static ValueMetric createMetricWithState(string state) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.add_slice_by_state(StringToId(state));
+ return metric;
+ }
+};
+
+/*
+ * Tests that the first bucket works correctly
+ */
+TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ int64_t startTimeBase = 11;
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ // statsd started long ago.
+ // The metric starts in the middle of the bucket
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+ logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase,
+ 22, pullerManager);
+
+ EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
+ EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
+ EXPECT_EQ(60 * NS_PER_SEC + startTimeBase,
+ valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC));
+ EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase,
+ valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC));
+}
+
+/*
+ * Tests that the first bucket works correctly
+ */
+TEST(ValueMetricProducerTest, TestFirstBucket) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ // statsd started long ago.
+ // The metric starts in the middle of the bucket
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+ logEventMatcherIndex, eventMatcherWizard, -1, 5,
+ 600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
+
+ EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
+ EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs());
+}
+
+/*
+ * Tests pulled atoms with no conditions
+ */
+TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
+
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(8, curInterval.value.long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 23));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(23, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(12, curInterval.value.long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+ EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
+
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(13, curInterval.value.long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+ EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
+ EXPECT_EQ(13, valueProducer->mPastBuckets.begin()->second[2].values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[2].mConditionTrueNs);
+}
+
+TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Initialize bucket.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 1));
+ return true;
+ }))
+ // Partial bucket.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 5));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+
+ // First bucket ends.
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 2));
+ valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
+
+ // Partial buckets created in 2nd bucket.
+ valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
+
+ // One full bucket and one partial bucket.
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ vector<ValueBucket> buckets = valueProducer->mPastBuckets.begin()->second;
+ EXPECT_EQ(2UL, buckets.size());
+ // Full bucket (2 - 1)
+ EXPECT_EQ(1, buckets[0].values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, buckets[0].mConditionTrueNs);
+ // Full bucket (5 - 3)
+ EXPECT_EQ(3, buckets[1].values[0].long_value);
+ // partial bucket [bucket2StartTimeNs, bucket2StartTimeNs + 2]
+ EXPECT_EQ(2, buckets[1].mConditionTrueNs);
+}
+
+/*
+ * Tests pulled atoms with filtering
+ */
+TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ auto keyValue = atomMatcher.add_field_value_matcher();
+ keyValue->set_field(1);
+ keyValue->set_eq_int(3);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateTwoValueLogEvent(tagId, bucketStartTimeNs, 3, 3));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+ kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 3, 11));
+
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(8, curInterval.value.long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+
+ allData.clear();
+ allData.push_back(CreateTwoValueLogEvent(tagId, bucket3StartTimeNs + 1, 4, 23));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ // No new data seen, so data has been cleared.
+ EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(8, curInterval.value.long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+
+ allData.clear();
+ allData.push_back(CreateTwoValueLogEvent(tagId, bucket4StartTimeNs + 1, 3, 36));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+
+ // the base was reset
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
+}
+
+/*
+ * Tests pulled atoms with no conditions and take absolute value after reset
+ */
+TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.set_use_absolute_value_on_reset(true);
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
+
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 10));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(10, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(10, curInterval.value.long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
+
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(26, curInterval.value.long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
+ EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+ EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
+}
+
+/*
+ * Tests pulled atoms with no conditions and take zero value after reset
+ */
+TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
+
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 10));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(10, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket4StartTimeNs + 1, 36));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(26, curInterval.value.long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+}
+
+/*
+ * Test pulled event with non sliced condition.
+ */
+TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 130));
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 180));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ // startUpdated:false sum:0 start:100
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ allData.push_back(CreateTwoValueLogEvent(tagId, bucket2StartTimeNs + 1, 1, 110));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(110, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(10, curInterval.value.long_value);
+
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(20, curInterval.value.long_value);
+ EXPECT_EQ(false, curBaseInfo.hasBase);
+
+ valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1});
+}
+
+TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
+
+ LogEvent event1(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+
+ valueProducer.notifyAppUpgrade(bucketStartTimeNs + 150, "ANY.APP", 1, 1);
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+ EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
+
+ LogEvent event2(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event2, tagId, bucketStartTimeNs + 59 * NS_PER_SEC, 1, 10);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+ EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
+
+ // Next value should create a new bucket.
+ LogEvent event3(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event3, tagId, bucketStartTimeNs + 65 * NS_PER_SEC, 1, 10);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+ EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+ EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
+}
+
+TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ .WillOnce(Return(true))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 149, 120));
+ return true;
+ }));
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 100));
+
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+
+ valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+ EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
+ assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {150});
+
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 150));
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+ EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+ EXPECT_EQ(20L,
+ valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
+ assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20, 30},
+ {150, bucketSizeNs - 150});
+}
+
+TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.set_split_bucket_for_app_upgrade(false);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 100));
+
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+
+ valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
+ EXPECT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+ EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+}
+
+TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 1, 100));
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs - 100, 120));
+ return true;
+ }));
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
+
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
+ EXPECT_FALSE(valueProducer->mCondition);
+
+ valueProducer->notifyAppUpgrade(bucket2StartTimeNs - 50, "ANY.APP", 1, 1);
+ // Expect one full buckets already done and starting a partial bucket.
+ EXPECT_EQ(bucket2StartTimeNs - 50, valueProducer->mCurrentBucketStartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+ EXPECT_EQ(bucketStartTimeNs,
+ valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20},
+ {(bucket2StartTimeNs - 100) - (bucketStartTimeNs + 1)});
+ EXPECT_FALSE(valueProducer->mCondition);
+}
+TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
+
+ LogEvent event1(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
+
+ LogEvent event2(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 1, 20);
+
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(10, curInterval.value.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(30, curInterval.value.long_value);
+
+ valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+ assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {30}, {bucketSizeNs});
+}
+
+TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
+ valueProducer.mCondition = ConditionState::kFalse;
+
+ LogEvent event1(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+ // has 1 slice
+ EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+
+ valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
+
+ LogEvent event2(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 1, 20);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(20, curInterval.value.long_value);
+
+ LogEvent event3(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event3, tagId, bucketStartTimeNs + 30, 1, 30);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(50, curInterval.value.long_value);
+
+ valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
+
+ LogEvent event4(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event4, tagId, bucketStartTimeNs + 40, 1, 40);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(50, curInterval.value.long_value);
+
+ valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+ assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {50}, {20});
+}
+
+TEST(ValueMetricProducerTest, TestAnomalyDetection) {
+ sp<AlarmMonitor> alarmMonitor;
+ Alert alert;
+ alert.set_id(101);
+ alert.set_metric_id(metricId);
+ alert.set_trigger_if_sum_gt(130);
+ alert.set_num_buckets(2);
+ const int32_t refPeriodSec = 3;
+ alert.set_refractory_period_secs(refPeriodSec);
+
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+ logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+
+ sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
+
+ LogEvent event1(/*uid=*/0, /*pid=*/0);
+ CreateRepeatedValueLogEvent(&event1, tagId, bucketStartTimeNs + 1 * NS_PER_SEC, 10);
+
+ LogEvent event2(/*uid=*/0, /*pid=*/0);
+ CreateRepeatedValueLogEvent(&event2, tagId, bucketStartTimeNs + 2 + NS_PER_SEC, 20);
+
+ LogEvent event3(/*uid=*/0, /*pid=*/0);
+ CreateRepeatedValueLogEvent(&event3, tagId,
+ bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC, 130);
+
+ LogEvent event4(/*uid=*/0, /*pid=*/0);
+ CreateRepeatedValueLogEvent(&event4, tagId,
+ bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC, 1);
+
+ LogEvent event5(/*uid=*/0, /*pid=*/0);
+ CreateRepeatedValueLogEvent(&event5, tagId,
+ bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC, 150);
+
+ LogEvent event6(/*uid=*/0, /*pid=*/0);
+ CreateRepeatedValueLogEvent(&event6, tagId,
+ bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC, 160);
+
+ // Two events in bucket #0.
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+ // Value sum == 30 <= 130.
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
+
+ // One event in bucket #2. No alarm as bucket #0 is trashed out.
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+ // Value sum == 130 <= 130.
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
+
+ // Three events in bucket #3.
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
+ // Anomaly at event 4 since Value sum == 131 > 130!
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+ std::ceil(1.0 * event4.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
+ // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+ std::ceil(1.0 * event4.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
+ // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
+ EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+ std::ceil(1.0 * event6.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+}
+
+// Test value metric no condition, the pull on bucket boundary come in time and too late
+TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+
+ vector<shared_ptr<LogEvent>> allData;
+ // pull 1
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 11));
+
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+
+ // startUpdated:true sum:0 start:11
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(11, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+
+ // pull 2 at correct time
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 23));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ // tartUpdated:false sum:12
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(23, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
+
+ // pull 3 come late.
+ // The previous bucket gets closed with error. (Has start value 23, no ending)
+ // Another bucket gets closed with error. (No start, but ending with 36)
+ // The new bucket is back to normal.
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket6StartTimeNs + 1, 36));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ // startUpdated:false sum:12
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(36, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
+}
+
+/*
+ * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
+ * was delivered late.
+ */
+TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // condition becomes true
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
+ return true;
+ }))
+ // condition becomes false
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
+ return true;
+ }));
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+
+ // pull on bucket boundary come late, condition change happens before it
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+ EXPECT_EQ(false, curBaseInfo.hasBase);
+
+ // Now the alarm is delivered.
+ // since the condition turned to off before this pull finish, it has no effect
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 110));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
+ EXPECT_EQ(false, curInterval.hasValue);
+}
+
+/*
+* Test pulled event with non sliced condition. The pull on boundary come late, after the
+condition
+* change to false, and then true again. This is due to alarm delivered late.
+*/
+TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // condition becomes true
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 8, 100));
+ return true;
+ }))
+ // condition becomes false
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 120));
+ return true;
+ }))
+ // condition becomes true again
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 25, 130));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ // startUpdated:false sum:0 start:100
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(100, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+
+ // pull on bucket boundary come late, condition change happens before it
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
+ EXPECT_EQ(false, curInterval.hasValue);
+
+ // condition changed to true again, before the pull alarm is delivered
+ valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(130, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+
+ // Now the alarm is delivered, but it is considered late, the data will be used
+ // for the new bucket since it was just pulled.
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 50, 140));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
+
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(140, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(10, curInterval.value.long_value);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 160));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20, 30},
+ {bucketSizeNs - 8, bucketSizeNs - 24});
+}
+
+TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.set_aggregation_type(ValueMetric::MIN);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
+
+ LogEvent event1(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
+
+ LogEvent event2(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 1, 20);
+
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(10, curInterval.value.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(10, curInterval.value.long_value);
+
+ valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+ assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10}, {bucketSizeNs});
+}
+
+TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.set_aggregation_type(ValueMetric::MAX);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
+
+ LogEvent event1(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
+
+ LogEvent event2(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 1, 20);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(10, curInterval.value.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(20, curInterval.value.long_value);
+
+ valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+ /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); */
+ /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); */
+ /* EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); */
+}
+
+TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.set_aggregation_type(ValueMetric::AVG);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
+
+ LogEvent event1(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
+
+ LogEvent event2(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 1, 15);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval;
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(10, curInterval.value.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(1, curInterval.sampleSize);
+
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(25, curInterval.value.long_value);
+ EXPECT_EQ(2, curInterval.sampleSize);
+
+ valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+
+ EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value -
+ 12.5) < epsilon);
+}
+
+TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.set_aggregation_type(ValueMetric::SUM);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
+
+ LogEvent event1(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
+
+ LogEvent event2(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event2, tagId, bucketStartTimeNs + 20, 1, 15);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(10, curInterval.value.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(25, curInterval.value.long_value);
+
+ valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+ assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {25}, {bucketSizeNs});
+}
+
+TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.set_aggregation_type(ValueMetric::MIN);
+ metric.set_use_diff(true);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
+
+ LogEvent event1(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10);
+
+ LogEvent event2(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event2, tagId, bucketStartTimeNs + 15, 1, 15);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(10, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(5, curInterval.value.long_value);
+
+ // no change in data.
+ LogEvent event3(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event3, tagId, bucket2StartTimeNs + 10, 1, 15);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(15, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+
+ LogEvent event4(/*uid=*/0, /*pid=*/0);
+ CreateTwoValueLogEvent(&event4, tagId, bucket2StartTimeNs + 15, 1, 15);
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(15, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+
+ valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+ assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {5}, {bucketSizeNs});
+}
+
+TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.mutable_value_field()->add_child()->set_field(3);
+ metric.set_aggregation_type(ValueMetric::MIN);
+ metric.set_use_diff(true);
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+ pullerManager);
+
+ LogEvent event1(/*uid=*/0, /*pid=*/0);
+ CreateThreeValueLogEvent(&event1, tagId, bucketStartTimeNs + 10, 1, 10, 20);
+
+ LogEvent event2(/*uid=*/0, /*pid=*/0);
+ CreateThreeValueLogEvent(&event2, tagId, bucketStartTimeNs + 15, 1, 15, 22);
+
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(10, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(20, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(5, curInterval.value.long_value);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(2, curInterval.value.long_value);
+
+ // no change in first value field
+ LogEvent event3(/*uid=*/0, /*pid=*/0);
+ CreateThreeValueLogEvent(&event3, tagId, bucket2StartTimeNs + 10, 1, 15, 25);
+
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(15, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(25, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+
+ LogEvent event4(/*uid=*/0, /*pid=*/0);
+ CreateThreeValueLogEvent(&event4, tagId, bucket2StartTimeNs + 15, 1, 15, 29);
+
+ valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
+ EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(15, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+ curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+ curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(29, curBaseInfo.base.long_value);
+ EXPECT_EQ(true, curInterval.hasValue);
+
+ valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
+ EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second[0].values.size());
+ EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second[1].values.size());
+
+ EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[0].mConditionTrueNs);
+ EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second[0].valueIndex[0]);
+ EXPECT_EQ(2, valueProducer.mPastBuckets.begin()->second[0].values[1].long_value);
+ EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].valueIndex[1]);
+
+ EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[1].mConditionTrueNs);
+ EXPECT_EQ(3, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
+ EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[1].valueIndex[0]);
+}
+
///*
// * Tests zero default base.
// */
-//TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
+// TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
// metric.mutable_dimensions_in_what()->set_field(tagId);
// metric.mutable_dimensions_in_what()->add_child()->set_field(1);
@@ -1774,7 +1576,7 @@
///*
// * Tests using zero default base with failed pull.
// */
-//TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
+// TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
// metric.mutable_dimensions_in_what()->set_field(tagId);
// metric.mutable_dimensions_in_what()->add_child()->set_field(1);
@@ -1885,8 +1687,9 @@
// it2 = std::next(valueProducer->mCurrentSlicedBucket.begin());
// interval1 = it->second[0];
// interval2 = it2->second[0];
-// baseInfo1 = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
-// baseInfo2 = valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
+// baseInfo1 =
+// valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0]; baseInfo2
+// = valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
//
// EXPECT_EQ(true, baseInfo1.hasBase);
// EXPECT_EQ(5, baseInfo1.base.long_value);
@@ -1905,7 +1708,7 @@
///*
// * Tests trim unused dimension key if no new data is seen in an entire bucket.
// */
-//TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
+// TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
// metric.mutable_dimensions_in_what()->set_field(tagId);
// metric.mutable_dimensions_in_what()->add_child()->set_field(1);
@@ -2023,7 +1826,7 @@
// EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
//}
//
-//TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) {
+// TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
//
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -2040,15 +1843,16 @@
// }));
//
// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager,
+// metric);
//
// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
// // has one slice
// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
// ValueMetricProducer::Interval& curInterval =
// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
+// ValueMetricProducer::BaseInfo& curBaseInfo =
+// valueProducer->mCurrentBaseInfo.begin()->second[0]; EXPECT_EQ(true, curBaseInfo.hasBase);
// EXPECT_EQ(100, curBaseInfo.base.long_value);
// EXPECT_EQ(false, curInterval.hasValue);
//
@@ -2060,7 +1864,7 @@
// EXPECT_EQ(false, valueProducer->mHasGlobalBase);
//}
//
-//TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
+// TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
//
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -2077,7 +1881,8 @@
// .WillOnce(Return(false));
//
// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager,
+// metric);
//
// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
//
@@ -2085,8 +1890,8 @@
// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
// ValueMetricProducer::Interval& curInterval =
// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
+// ValueMetricProducer::BaseInfo& curBaseInfo =
+// valueProducer->mCurrentBaseInfo.begin()->second[0]; EXPECT_EQ(true, curBaseInfo.hasBase);
// EXPECT_EQ(100, curBaseInfo.base.long_value);
// EXPECT_EQ(false, curInterval.hasValue);
// EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
@@ -2100,7 +1905,7 @@
// EXPECT_EQ(false, valueProducer->mHasGlobalBase);
//}
//
-//TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
+// TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
//
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -2125,7 +1930,8 @@
// }));
//
// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager,
+// metric);
//
// // Don't directly set mCondition; the real code never does that. Go through regular code path
// // to avoid unexpected behaviors.
@@ -2138,13 +1944,13 @@
// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
// ValueMetricProducer::Interval& curInterval =
// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(false, curBaseInfo.hasBase);
+// ValueMetricProducer::BaseInfo curBaseInfo =
+// valueProducer->mCurrentBaseInfo.begin()->second[0]; EXPECT_EQ(false, curBaseInfo.hasBase);
// EXPECT_EQ(false, curInterval.hasValue);
// EXPECT_EQ(false, valueProducer->mHasGlobalBase);
//}
//
-//TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
+// TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
// metric.set_condition(StringToId("SCREEN_ON"));
// metric.set_max_pull_delay_sec(0);
@@ -2162,7 +1968,8 @@
// }));
//
// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager,
+// metric);
//
// valueProducer->mCondition = ConditionState::kFalse;
//
@@ -2171,7 +1978,7 @@
// EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
//}
//
-//TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
+// TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
//
// UidMap uidMap;
@@ -2196,7 +2003,7 @@
// EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
//}
//
-//TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
+// TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
//
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -2212,7 +2019,8 @@
// }));
//
// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager,
+// metric);
//
// valueProducer->mCondition = ConditionState::kFalse;
// valueProducer->mHasGlobalBase = false;
@@ -2222,8 +2030,8 @@
// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
// ValueMetricProducer::Interval& curInterval =
// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
+// ValueMetricProducer::BaseInfo curBaseInfo =
+// valueProducer->mCurrentBaseInfo.begin()->second[0]; EXPECT_EQ(true, curBaseInfo.hasBase);
// EXPECT_EQ(100, curBaseInfo.base.long_value);
// EXPECT_EQ(false, curInterval.hasValue);
// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2232,7 +2040,7 @@
///*
// * Tests that a bucket is marked invalid when a condition change pull fails.
// */
-//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed) {
+// TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
//
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -2251,7 +2059,8 @@
// }));
//
// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager,
+// metric);
//
// valueProducer->mCondition = ConditionState::kTrue;
//
@@ -2286,8 +2095,8 @@
// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
// ValueMetricProducer::Interval& curInterval =
// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
+// ValueMetricProducer::BaseInfo curBaseInfo =
+// valueProducer->mCurrentBaseInfo.begin()->second[0]; EXPECT_EQ(true, curBaseInfo.hasBase);
// EXPECT_EQ(140, curBaseInfo.base.long_value);
// EXPECT_EQ(false, curInterval.hasValue);
// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2317,7 +2126,7 @@
///*
// * Tests that a bucket is marked invalid when the guardrail is hit.
// */
-//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) {
+// TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
// metric.mutable_dimensions_in_what()->set_field(tagId);
// metric.mutable_dimensions_in_what()->add_child()->set_field(1);
@@ -2339,7 +2148,8 @@
// }));
//
// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager,
+// metric);
// valueProducer->mCondition = ConditionState::kFalse;
//
// valueProducer->onConditionChanged(true, bucketStartTimeNs + 2);
@@ -2385,7 +2195,7 @@
///*
// * Tests that a bucket is marked invalid when the bucket's initial pull fails.
// */
-//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed) {
+// TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
//
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -2412,7 +2222,8 @@
// }));
//
// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager,
+// metric);
//
// valueProducer->mCondition = ConditionState::kTrue;
//
@@ -2445,8 +2256,8 @@
// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
// ValueMetricProducer::Interval& curInterval =
// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
+// ValueMetricProducer::BaseInfo curBaseInfo =
+// valueProducer->mCurrentBaseInfo.begin()->second[0]; EXPECT_EQ(true, curBaseInfo.hasBase);
// EXPECT_EQ(140, curBaseInfo.base.long_value);
// EXPECT_EQ(false, curInterval.hasValue);
// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
@@ -2477,7 +2288,7 @@
// * Tests that a bucket is marked invalid when the bucket's final pull fails
// * (i.e. failed pull on bucket boundary).
// */
-//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
+// TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
//
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -2504,7 +2315,8 @@
// }));
//
// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager,
+// metric);
//
// valueProducer->mCondition = ConditionState::kTrue;
//
@@ -2537,8 +2349,8 @@
// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
// ValueMetricProducer::Interval& curInterval =
// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(false, curBaseInfo.hasBase);
+// ValueMetricProducer::BaseInfo curBaseInfo =
+// valueProducer->mCurrentBaseInfo.begin()->second[0]; EXPECT_EQ(false, curBaseInfo.hasBase);
// EXPECT_EQ(false, curInterval.hasValue);
// EXPECT_EQ(false, valueProducer->mHasGlobalBase);
//
@@ -2564,7 +2376,7 @@
// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs), dropEvent.drop_time_millis());
//}
//
-//TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
+// TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
// EXPECT_CALL(*pullerManager, Pull(tagId, _))
@@ -2604,999 +2416,903 @@
// EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
//}
-//
-//TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // First onConditionChanged
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-// event->write(tagId);
-// event->write(3);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-//
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval& curInterval =
-// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-//
-// // Empty pull.
-// valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(false, curBaseInfo.hasBase);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(false, valueProducer->mHasGlobalBase);
-//}
-//
-//TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // First onConditionChanged
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-// event->write(tagId);
-// event->write(1);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-// event->write(tagId);
-// event->write(2);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-// event->write(tagId);
-// event->write(5);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-//
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-// valueProducer->onConditionChanged(false, bucketStartTimeNs + 11);
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval& curInterval =
-// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(true, curInterval.hasValue);
-// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-//
-// // End of bucket
-// vector<shared_ptr<LogEvent>> allData;
-// allData.clear();
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// // Data is empty, base should be reset.
-// EXPECT_EQ(false, curBaseInfo.hasBase);
-// EXPECT_EQ(5, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-//
-// EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1}, {bucketSizeNs - 12 + 1});
-//}
-//
-//TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// metric.mutable_dimensions_in_what()->set_field(tagId);
-// metric.mutable_dimensions_in_what()->add_child()->set_field(1);
-// metric.set_condition(StringToId("SCREEN_ON"));
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // First onConditionChanged
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-// event->write(tagId);
-// event->write(1);
-// event->write(1);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-//
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-//
-// // End of bucket
-// vector<shared_ptr<LogEvent>> allData;
-// allData.clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-// event->write(2);
-// event->write(2);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-//
-// // Key 1 should be reset since in not present in the most pull.
-// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-// auto iterator = valueProducer->mCurrentSlicedBucket.begin();
-// auto baseInfoIter = valueProducer->mCurrentBaseInfo.begin();
-// EXPECT_EQ(true, baseInfoIter->second[0].hasBase);
-// EXPECT_EQ(2, baseInfoIter->second[0].base.long_value);
-// EXPECT_EQ(false, iterator->second[0].hasValue);
-// iterator++;
-// baseInfoIter++;
-// EXPECT_EQ(false, baseInfoIter->second[0].hasBase);
-// EXPECT_EQ(1, baseInfoIter->second[0].base.long_value);
-// EXPECT_EQ(false, iterator->second[0].hasValue);
-//
-// EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-//}
-//
-//TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // Initialization.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
-// return true;
-// }))
-// // notifyAppUpgrade.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(ValueMetricProducerTestHelper::createEvent(
-// bucketStartTimeNs + bucketSizeNs / 2, 10));
-// return true;
-// }));
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-// ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
-//
-// valueProducer->notifyAppUpgrade(bucketStartTimeNs + bucketSizeNs / 2, "com.foo", 10000, 1);
-// ASSERT_EQ(1UL, valueProducer->mCurrentFullBucket.size());
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 1, 4));
-// valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1);
-// ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
-//}
-//
-//TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // Second onConditionChanged.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(
-// ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 10, 5));
-// return true;
-// }))
-// // Third onConditionChanged.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(
-// ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 10, 7));
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-// valueProducer->mCondition = ConditionState::kUnknown;
-//
-// valueProducer->onConditionChanged(false, bucketStartTimeNs);
-// ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-//
-// // End of first bucket
-// vector<shared_ptr<LogEvent>> allData;
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 4));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
-// ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-//
-// valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
-// ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curBaseInfo.hasBase);
-// EXPECT_EQ(5, curBaseInfo.base.long_value);
-// EXPECT_EQ(false, curInterval.hasValue);
-//
-// valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
-//
-// // Bucket should have been completed.
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {bucketSizeNs - 10});
-//}
-//
-//TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// metric.set_use_diff(false);
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
-//
-// allData.clear();
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-//
-// // Bucket should have been completed.
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs});
-//}
-//
-//TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // Initialization.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
-//
-// allData.clear();
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-//
-// // Bucket should have been completed.
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {19}, {bucketSizeNs});
-//}
-//
-//TEST(ValueMetricProducerTest, TestBucketBoundariesOnAppUpgrade) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // Initialization.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
-// return true;
-// }))
-// // notifyAppUpgrade.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(
-// ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 2, 10));
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-//
-// valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
-//
-// // Bucket should have been completed.
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9}, {bucketSizeNs});
-//}
-//
-//TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // First on condition changed.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
-// return true;
-// }))
-// // Second on condition changed.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 3));
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-//
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-// valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
-// valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
-//
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(true, curInterval.hasValue);
-// EXPECT_EQ(2, curInterval.value.long_value);
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 10));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
-//
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {2});
-//}
-//
-//// TODO: b/145705635 fix or delete this test
-//TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // First condition change.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
-// return true;
-// }))
-// // 2nd condition change.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
-// return true;
-// }))
-// // 3rd condition change.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-// valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 3, 10));
-// valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs + 3);
-//
-// allData.clear();
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
-// valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
-//
-// valueProducer->onConditionChanged(false, bucket2StartTimeNs + 8);
-// valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
-//
-// allData.clear();
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 30));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-//
-// // There was not global base available so all buckets are invalid.
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
-//}
-//
-//TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-//
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // Initial pull.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-// event->write(tagId);
-// event->write(1);
-// event->write(1);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, tagId, bucketStartTimeNs,
-// bucketStartTimeNs, pullerManager);
-//
-// ProtoOutputStream output;
-// std::set<string> strSet;
-// valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
-// FAST, &strSet, &output);
-//
-// StatsLogReport report = outputStreamToProto(&output);
-// // Bucket is invalid since we did not pull when dump report was called.
-// EXPECT_EQ(0, report.value_metrics().data_size());
-//}
-//
-//TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-//
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // Initial pull.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-// event->write(tagId);
-// event->write(1);
-// event->write(1);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, tagId, bucketStartTimeNs,
-// bucketStartTimeNs, pullerManager);
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-// event->write(tagId);
-// event->write(2);
-// event->write(2);
-// event->init();
-// allData.push_back(event);
-// valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-//
-// ProtoOutputStream output;
-// std::set<string> strSet;
-// valueProducer.onDumpReport(bucket4StartTimeNs, false /* include recent buckets */, true, FAST,
-// &strSet, &output);
-//
-// StatsLogReport report = outputStreamToProto(&output);
-// // Previous bucket is part of the report.
-// EXPECT_EQ(1, report.value_metrics().data_size());
-// EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num());
-//}
-//
-//TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-//
-// UidMap uidMap;
-// SimpleAtomMatcher atomMatcher;
-// atomMatcher.set_atom_id(tagId);
-// sp<EventMatcherWizard> eventMatcherWizard =
-// new EventMatcherWizard({new SimpleLogMatchingTracker(
-// atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-// sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-// EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-//
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // Initial pull.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-// event->write(tagId);
-// event->write(1);
-// event->write(1);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-// event->write(tagId);
-// event->write(3);
-// event->write(3);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-// eventMatcherWizard, tagId, bucketStartTimeNs,
-// bucketStartTimeNs, pullerManager);
-//
-// ProtoOutputStream output;
-// std::set<string> strSet;
-// valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
-// NO_TIME_CONSTRAINTS, &strSet, &output);
-//
-// StatsLogReport report = outputStreamToProto(&output);
-// EXPECT_EQ(1, report.value_metrics().data_size());
-// EXPECT_EQ(1, report.value_metrics().data(0).bucket_info_size());
-// EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
-//}
-//
-//TEST(ValueMetricProducerTest, TestPulledData_noDiff_withoutCondition) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-// metric.set_use_diff(false);
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-//
-// vector<shared_ptr<LogEvent>> allData;
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 10));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 30);
-//
-// // Bucket should have been completed.
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs});
-//}
-//
-//TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-// metric.set_use_diff(false);
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // condition becomes true
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(
-// ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
-// return true;
-// }))
-// // condition becomes false
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(
-// ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 50, 20));
-// return true;
-// }));
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-// valueProducer->mCondition = ConditionState::kFalse;
-//
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-// valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
-// // has one slice
-// EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-// ValueMetricProducer::Interval curInterval =
-// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(false, curBaseInfo.hasBase);
-// EXPECT_EQ(true, curInterval.hasValue);
-// EXPECT_EQ(20, curInterval.value.long_value);
-//
-// // Now the alarm is delivered. Condition is off though.
-// vector<shared_ptr<LogEvent>> allData;
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-//
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8});
-// curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(false, curBaseInfo.hasBase);
-// EXPECT_EQ(false, curInterval.hasValue);
-//}
-//
-//TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-// metric.set_use_diff(false);
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // condition becomes true
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(
-// ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
-// return true;
-// }));
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-// valueProducer->mCondition = ConditionState::kFalse;
-//
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-//
-// // Now the alarm is delivered. Condition is off though.
-// vector<shared_ptr<LogEvent>> allData;
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-//
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8});
-// ValueMetricProducer::Interval curInterval =
-// valueProducer->mCurrentSlicedBucket.begin()->second[0];
-// ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-// EXPECT_EQ(false, curBaseInfo.hasBase);
-// EXPECT_EQ(false, curInterval.hasValue);
-//}
-//
-//TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryFalse) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-// metric.set_use_diff(false);
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-// valueProducer->mCondition = ConditionState::kFalse;
-//
-// // Now the alarm is delivered. Condition is off though.
-// vector<shared_ptr<LogEvent>> allData;
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-//
-// // Condition was always false.
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
-//}
-//
-//TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-// metric.set_use_diff(false);
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // condition becomes true
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// data->push_back(
-// ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
-// return true;
-// }))
-// .WillOnce(Return(false));
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-// valueProducer->mCondition = ConditionState::kFalse;
-//
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-// valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
-//
-// // Now the alarm is delivered. Condition is off though.
-// vector<shared_ptr<LogEvent>> allData;
-// allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
-// valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-//
-// // No buckets, we had a failure.
-// assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
-//}
-//
-///*
-// * Test that DUMP_REPORT_REQUESTED dump reason is logged.
-// *
-// * For the bucket to be marked invalid during a dump report requested,
-// * three things must be true:
-// * - we want to include the current partial bucket
-// * - we need a pull (metric is pulled and condition is true)
-// * - the dump latency must be FAST
-// */
-//
-//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequested) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // Condition change to true.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-// event->write("field1");
-// event->write(10);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-//
-// // Condition change event.
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
-//
-// // Check dump report.
-// ProtoOutputStream output;
-// std::set<string> strSet;
-// valueProducer->onDumpReport(bucketStartTimeNs + 40, true /* include recent buckets */, true,
-// FAST /* dumpLatency */, &strSet, &output);
-//
-// StatsLogReport report = outputStreamToProto(&output);
-// EXPECT_TRUE(report.has_value_metrics());
-// EXPECT_EQ(0, report.value_metrics().data_size());
-// EXPECT_EQ(1, report.value_metrics().skipped_size());
-//
-// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40),
-// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-//
-// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-// EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
-// EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40), dropEvent.drop_time_millis());
-//}
-//
-///*
-// * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late condition
-// * change event (i.e. the condition change occurs in the wrong bucket).
-// */
-//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWrongBucket) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // Condition change to true.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
-// event->write("field1");
-// event->write(10);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-//
-// // Condition change event.
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
-//
-// // Bucket boundary pull.
-// vector<shared_ptr<LogEvent>> allData;
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
-// event->write("field1");
-// event->write(15);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
-//
-// // Late condition change event.
-// valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
-//
-// // Check dump report.
-// ProtoOutputStream output;
-// std::set<string> strSet;
-// valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
-// NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-//
-// StatsLogReport report = outputStreamToProto(&output);
-// EXPECT_TRUE(report.has_value_metrics());
-// EXPECT_EQ(1, report.value_metrics().data_size());
-// EXPECT_EQ(1, report.value_metrics().skipped_size());
-//
-// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
-// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
-// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-//
-// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-// EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
-// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
-//}
-//
-///*
-// * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late accumulate
-// * event (i.e. the accumulate events call occurs in the wrong bucket).
-// */
-//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWrongBucket) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // Condition change to true.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
-// event->write("field1");
-// event->write(10);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// // Dump report requested.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 100);
-// event->write("field1");
-// event->write(15);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-//
-// // Condition change event.
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
-//
-// // Bucket boundary pull.
-// vector<shared_ptr<LogEvent>> allData;
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
-// event->write("field1");
-// event->write(15);
-// event->init();
-// allData.push_back(event);
-// valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
-//
-// allData.clear();
-// event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
-// event->write("field1");
-// event->write(20);
-// event->init();
-// allData.push_back(event);
-//
-// // Late accumulateEvents event.
-// valueProducer->accumulateEvents(allData, bucket2StartTimeNs - 100, bucket2StartTimeNs - 100);
-//
-// // Check dump report.
-// ProtoOutputStream output;
-// std::set<string> strSet;
-// valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
-// NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-//
-// StatsLogReport report = outputStreamToProto(&output);
-// EXPECT_TRUE(report.has_value_metrics());
-// EXPECT_EQ(1, report.value_metrics().data_size());
-// EXPECT_EQ(1, report.value_metrics().skipped_size());
-//
-// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
-// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
-// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-//
-// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-// EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
-// EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
-//}
-//
-///*
-// * Test that CONDITION_UNKNOWN dump reason is logged due to an unknown condition
-// * when a metric is initialized.
-// */
-//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // Condition change to true.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
-// event->write("field1");
-// event->write(10);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// // Dump report requested.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 100);
-// event->write("field1");
-// event->write(15);
-// event->init();
-// data->push_back(event);
-// return true;
-// }));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
-// metric);
-//
-// // Condition change event.
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
-//
-// // Check dump report.
-// ProtoOutputStream output;
-// std::set<string> strSet;
-// int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
-// valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
-// NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-//
-// StatsLogReport report = outputStreamToProto(&output);
-// EXPECT_TRUE(report.has_value_metrics());
-// EXPECT_EQ(0, report.value_metrics().data_size());
-// EXPECT_EQ(1, report.value_metrics().skipped_size());
-//
-// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-// EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
-// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-//
-// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-// EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
-// EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
-//}
-//
-///*
-// * Test that PULL_FAILED dump reason is logged due to a pull failure in
-// * #pullAndMatchEventsLocked.
-// */
-//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) {
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-//
-// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-// EXPECT_CALL(*pullerManager, Pull(tagId, _))
-// // Condition change to true.
-// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
-// event->write("field1");
-// event->write(10);
-// event->init();
-// data->push_back(event);
-// return true;
-// }))
-// // Dump report requested, pull fails.
-// .WillOnce(Return(false));
-//
-// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-//
-// // Condition change event.
-// valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
-//
-// // Check dump report.
-// ProtoOutputStream output;
-// std::set<string> strSet;
-// int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
-// valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
-// NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-//
-// StatsLogReport report = outputStreamToProto(&output);
-// EXPECT_TRUE(report.has_value_metrics());
-// EXPECT_EQ(0, report.value_metrics().data_size());
-// EXPECT_EQ(1, report.value_metrics().skipped_size());
-//
-// EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-// report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-// EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
-// report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-// EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-//
-// auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-// EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-// EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
-//}
-//
+
+TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // First onConditionChanged
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval& curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+
+ // Empty pull.
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(false, valueProducer->mHasGlobalBase);
+}
+
+TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // First onConditionChanged
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 2));
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 5));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 11);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval& curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+
+ // End of bucket
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ // Data is empty, base should be reset.
+ EXPECT_EQ(false, curBaseInfo.hasBase);
+ EXPECT_EQ(5, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1}, {bucketSizeNs - 12 + 1});
+}
+
+TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.mutable_dimensions_in_what()->set_field(tagId);
+ metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+ metric.set_condition(StringToId("SCREEN_ON"));
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // First onConditionChanged
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+
+ // End of bucket
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 2));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ // Key 1 should be reset since in not present in the most pull.
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ auto iterator = valueProducer->mCurrentSlicedBucket.begin();
+ auto baseInfoIter = valueProducer->mCurrentBaseInfo.begin();
+ EXPECT_EQ(true, baseInfoIter->second[0].hasBase);
+ EXPECT_EQ(2, baseInfoIter->second[0].base.long_value);
+ EXPECT_EQ(false, iterator->second[0].hasValue);
+ iterator++;
+ baseInfoIter++;
+ EXPECT_EQ(false, baseInfoIter->second[0].hasBase);
+ EXPECT_EQ(1, baseInfoIter->second[0].base.long_value);
+ EXPECT_EQ(false, iterator->second[0].hasValue);
+
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+}
+
+TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Initialization.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
+ // notifyAppUpgrade.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(
+ tagId, bucketStartTimeNs + bucketSizeNs / 2, 10));
+ return true;
+ }));
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+ ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
+
+ valueProducer->notifyAppUpgrade(bucketStartTimeNs + bucketSizeNs / 2, "com.foo", 10000, 1);
+ ASSERT_EQ(1UL, valueProducer->mCurrentFullBucket.size());
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 1, 4));
+ valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1);
+ ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
+}
+
+TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Second onConditionChanged.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 10, 5));
+ return true;
+ }))
+ // Third onConditionChanged.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs + 10, 7));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+ valueProducer->mCondition = ConditionState::kUnknown;
+
+ valueProducer->onConditionChanged(false, bucketStartTimeNs);
+ ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+
+ // End of first bucket
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 4));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
+ ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+
+ valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
+ ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curBaseInfo.hasBase);
+ EXPECT_EQ(5, curBaseInfo.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+
+ valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
+
+ // Bucket should have been completed.
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {bucketSizeNs - 10});
+}
+
+TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.set_use_diff(false);
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
+
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ // Bucket should have been completed.
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs});
+}
+
+TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Initialization.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
+
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ // Bucket should have been completed.
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {19}, {bucketSizeNs});
+}
+
+TEST(ValueMetricProducerTest, TestBucketBoundariesOnAppUpgrade) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Initialization.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
+ // notifyAppUpgrade.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 2, 10));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+
+ valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
+
+ // Bucket should have been completed.
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9}, {bucketSizeNs});
+}
+
+TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // First on condition changed.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
+ // Second on condition changed.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 3));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(2, curInterval.value.long_value);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 1, 10));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
+
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {2});
+}
+
+// TODO: b/145705635 fix or delete this test
+TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // First condition change.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs, 1));
+ return true;
+ }))
+ // 2nd condition change.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
+ return true;
+ }))
+ // 3rd condition change.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 1));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+ valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 3, 10));
+ valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs + 3);
+
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 20));
+ valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs + 8);
+ valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
+
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket3StartTimeNs, 30));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ // There was not global base available so all buckets are invalid.
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
+}
+
+TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Initial pull.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
+ return true;
+ }));
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
+ FAST, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ // Bucket is invalid since we did not pull when dump report was called.
+ EXPECT_EQ(0, report.value_metrics().data_size());
+}
+
+TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Initial pull.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
+ return true;
+ }));
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ allData.push_back(CreateThreeValueLogEvent(tagId, bucket2StartTimeNs + 1, tagId, 2, 2));
+ valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer.onDumpReport(bucket4StartTimeNs, false /* include recent buckets */, true, FAST,
+ &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ // Previous bucket is part of the report.
+ EXPECT_EQ(1, report.value_metrics().data_size());
+ EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num());
+}
+
+TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Initial pull.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateThreeValueLogEvent(tagId, bucketStartTimeNs, tagId, 1, 1));
+ return true;
+ }))
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(
+ CreateThreeValueLogEvent(tagId, bucketStartTimeNs + 10, tagId, 3, 3));
+ return true;
+ }));
+
+ ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_EQ(1, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().data(0).bucket_info_size());
+ EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+}
+
+TEST(ValueMetricProducerTest, TestPulledData_noDiff_withoutCondition) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.set_use_diff(false);
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 10));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 30);
+
+ // Bucket should have been completed.
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs});
+}
+
+TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+ metric.set_use_diff(false);
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // condition becomes true
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
+ return true;
+ }))
+ // condition becomes false
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 20));
+ return true;
+ }));
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+ valueProducer->mCondition = ConditionState::kFalse;
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
+ // has one slice
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(20, curInterval.value.long_value);
+
+ // Now the alarm is delivered. Condition is off though.
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 110));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8});
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
+ EXPECT_EQ(false, curInterval.hasValue);
+}
+
+TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+ metric.set_use_diff(false);
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // condition becomes true
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
+ return true;
+ }));
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+ valueProducer->mCondition = ConditionState::kFalse;
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+
+ // Now the alarm is delivered. Condition is off though.
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8});
+ ValueMetricProducer::Interval curInterval =
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+ EXPECT_EQ(false, curBaseInfo.hasBase);
+ EXPECT_EQ(false, curInterval.hasValue);
+}
+
+TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryFalse) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+ metric.set_use_diff(false);
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+ valueProducer->mCondition = ConditionState::kFalse;
+
+ // Now the alarm is delivered. Condition is off though.
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ // Condition was always false.
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
+}
+
+TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+ metric.set_use_diff(false);
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // condition becomes true
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 30, 10));
+ return true;
+ }))
+ .WillOnce(Return(false));
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+ valueProducer->mCondition = ConditionState::kFalse;
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
+
+ // Now the alarm is delivered. Condition is off though.
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 30, 30));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ // No buckets, we had a failure.
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
+}
+
+/*
+ * Test that DUMP_REPORT_REQUESTED dump reason is logged.
+ *
+ * For the bucket to be marked invalid during a dump report requested,
+ * three things must be true:
+ * - we want to include the current partial bucket
+ * - we need a pull (metric is pulled and condition is true)
+ * - the dump latency must be FAST
+ */
+
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequested) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Condition change to true.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 20, 10));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ // Condition change event.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucketStartTimeNs + 40, true /* include recent buckets */, true,
+ FAST /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late condition
+ * change event (i.e. the condition change occurs in the wrong bucket).
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWrongBucket) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Condition change to true.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ // Condition change event.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+
+ // Bucket boundary pull.
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 15));
+ valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+
+ // Late condition change event.
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(1, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late accumulate
+ * event (i.e. the accumulate events call occurs in the wrong bucket).
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWrongBucket) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Condition change to true.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
+ return true;
+ }))
+ // Dump report requested.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs + 100, 15));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ // Condition change event.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+
+ // Bucket boundary pull.
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs, 15));
+ valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+
+ allData.clear();
+ allData.push_back(CreateRepeatedValueLogEvent(tagId, bucket2StartTimeNs - 100, 20));
+
+ // Late accumulateEvents event.
+ valueProducer->accumulateEvents(allData, bucket2StartTimeNs - 100, bucket2StartTimeNs - 100);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(1, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test that CONDITION_UNKNOWN dump reason is logged due to an unknown condition
+ * when a metric is initialized.
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Condition change to true.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
+ return true;
+ }))
+ // Dump report requested.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 100, 15));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
+ metric);
+
+ // Condition change event.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
+ valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
+}
+
+/*
+ * Test that PULL_FAILED dump reason is logged due to a pull failure in
+ * #pullAndMatchEventsLocked.
+ */
+TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Condition change to true.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(CreateRepeatedValueLogEvent(tagId, bucketStartTimeNs + 50, 10));
+ return true;
+ }))
+ // Dump report requested, pull fails.
+ .WillOnce(Return(false));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ // Condition change event.
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+
+ // Check dump report.
+ ProtoOutputStream output;
+ std::set<string> strSet;
+ int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
+ valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
+ NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+
+ StatsLogReport report = outputStreamToProto(&output);
+ EXPECT_TRUE(report.has_value_metrics());
+ EXPECT_EQ(0, report.value_metrics().data_size());
+ EXPECT_EQ(1, report.value_metrics().skipped_size());
+
+ EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+ report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+ EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
+ report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+ EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+
+ auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+ EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+ EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
+}
+
///*
// * Test that MULTIPLE_BUCKETS_SKIPPED dump reason is logged when a log event
// * skips over more than one bucket.
// */
-//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSkipped) {
+// TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSkipped) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
//
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -3624,7 +3340,8 @@
// }));
//
// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager,
+// metric);
//
// // Condition change event.
// valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
@@ -3635,7 +3352,8 @@
// // Check dump report.
// ProtoOutputStream output;
// std::set<string> strSet;
-// valueProducer->onDumpReport(bucket4StartTimeNs + 1000, true /* include recent buckets */, true,
+// valueProducer->onDumpReport(bucket4StartTimeNs + 1000, true /* include recent buckets */,
+// true,
// NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
//
// StatsLogReport report = outputStreamToProto(&output);
@@ -3658,7 +3376,7 @@
// * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
// * is smaller than the "min_bucket_size_nanos" specified in the metric config.
// */
-//TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
+// TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
// metric.set_min_bucket_size_nanos(10000000000); // 10 seconds
//
@@ -3687,7 +3405,8 @@
// }));
//
// sp<ValueMetricProducer> valueProducer =
-// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+// ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager,
+// metric);
//
// // Condition change event.
// valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
@@ -3718,7 +3437,7 @@
///*
// * Test multiple bucket drop events in the same bucket.
// */
-//TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) {
+// TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
//
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -3772,7 +3491,7 @@
// * Test that the number of logged bucket drop events is capped at the maximum.
// * The maximum is currently 10 and is set in MetricProducer::maxDropEventsReached().
// */
-//TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
+// TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
//
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -3800,10 +3519,8 @@
// .WillOnce(Return(false))
// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 220);
-// event->write("field1");
-// event->write(10);
-// event->init();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs +
+// 220); event->write("field1"); event->write(10); event->init();
// data->push_back(event);
// return true;
// }));
@@ -3896,7 +3613,7 @@
// * - Using diff
// * - Second field is value field
// */
-//TEST(ValueMetricProducerTest, TestSlicedState) {
+// TEST(ValueMetricProducerTest, TestSlicedState) {
// // Set up ValueMetricProducer.
// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -3954,7 +3671,7 @@
//
// sp<ValueMetricProducer> valueProducer =
// ValueMetricProducerTestHelper::createValueProducerWithState(
-// pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, {});
+// pullerManager, metric, {util::SCREEN_STATE_CHANGED}, {});
//
// // Set up StateManager and check that StateTrackers are initialized.
// StateManager::getInstance().clear();
@@ -3987,7 +3704,8 @@
// EXPECT_EQ(2, it->second[0].value.long_value);
//
// // Bucket status after screen state change ON->OFF.
-// screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// screenEvent =
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
// bucketStartTimeNs + 10);
// StateManager::getInstance().onLogEvent(*screenEvent);
// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
@@ -4067,9 +3785,10 @@
// * - Using diff
// * - Second field is value field
// */
-//TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
+// TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
// // Set up ValueMetricProducer.
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
+// ValueMetric metric =
+// ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
// sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
// EXPECT_CALL(*pullerManager, Pull(tagId, _))
// // ValueMetricProducer initialized.
@@ -4136,7 +3855,7 @@
//
// sp<ValueMetricProducer> valueProducer =
// ValueMetricProducerTestHelper::createValueProducerWithState(
-// pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, stateGroupMap);
+// pullerManager, metric, {util::SCREEN_STATE_CHANGED}, stateGroupMap);
//
// // Set up StateManager and check that StateTrackers are initialized.
// StateManager::getInstance().clear();
@@ -4189,7 +3908,8 @@
// EXPECT_EQ(2, it->second[0].value.long_value);
//
// // Bucket status after screen state change VR->OFF.
-// screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+// screenEvent =
+// CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
// bucketStartTimeNs + 15);
// StateManager::getInstance().onLogEvent(*screenEvent);
// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
@@ -4243,9 +3963,10 @@
// * - Using diff
// * - Second field is value field
// */
-//TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
+// TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
// // Set up ValueMetricProducer.
-// ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("UID_PROCESS_STATE");
+// ValueMetric metric =
+// ValueMetricProducerTestHelper::createMetricWithState("UID_PROCESS_STATE");
// metric.mutable_dimensions_in_what()->set_field(tagId);
// metric.mutable_dimensions_in_what()->add_child()->set_field(1);
//
@@ -4311,10 +4032,8 @@
// // Uid 1 process state change from Foreground -> Background
// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
-// event->write(1 /* uid */);
-// event->write(13);
-// event->init();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs +
+// 20); event->write(1 /* uid */); event->write(13); event->init();
// data->push_back(event);
//
// // This event should be skipped.
@@ -4328,10 +4047,8 @@
// // Uid 1 process state change from Background -> Foreground
// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
-// event->write(1 /* uid */);
-// event->write(17);
-// event->init();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs +
+// 40); event->write(1 /* uid */); event->write(17); event->init();
// data->push_back(event);
//
// // This event should be skipped.
@@ -4345,10 +4062,8 @@
// // Dump report pull.
// .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
// data->clear();
-// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
-// event->write(2 /* uid */);
-// event->write(20);
-// event->init();
+// shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs +
+// 50); event->write(2 /* uid */); event->write(20); event->init();
// data->push_back(event);
//
// event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
@@ -4393,7 +4108,8 @@
//
// // Bucket status after uid 1 process state change kStateUnknown -> Foreground.
// auto uidProcessEvent = CreateUidProcessStateChangedEvent(
-// 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucketStartTimeNs + 20);
+// 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucketStartTimeNs +
+// 20);
// StateManager::getInstance().onLogEvent(*uidProcessEvent);
// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
// // Base for dimension key {uid 1}.
@@ -4420,7 +4136,8 @@
//
// // Bucket status after uid 2 process state change kStateUnknown -> Background.
// uidProcessEvent = CreateUidProcessStateChangedEvent(
-// 2 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucketStartTimeNs + 40);
+// 2 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucketStartTimeNs +
+// 40);
// StateManager::getInstance().onLogEvent(*uidProcessEvent);
// EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
// // Base for dimension key {uid 1}.
@@ -4499,7 +4216,8 @@
//
// // Bucket status after uid 1 process state change from Foreground -> Background.
// uidProcessEvent = CreateUidProcessStateChangedEvent(
-// 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucket2StartTimeNs + 20);
+// 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucket2StartTimeNs +
+// 20);
// StateManager::getInstance().onLogEvent(*uidProcessEvent);
//
// EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
@@ -4533,7 +4251,8 @@
//
// // Bucket status after uid 1 process state change Background->Foreground.
// uidProcessEvent = CreateUidProcessStateChangedEvent(
-// 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucket2StartTimeNs + 40);
+// 1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucket2StartTimeNs +
+// 40);
// StateManager::getInstance().onLogEvent(*uidProcessEvent);
//
// EXPECT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
diff --git a/cmds/statsd/tests/state/StateTracker_test.cpp b/cmds/statsd/tests/state/StateTracker_test.cpp
index 36c0f32..b1633c6 100644
--- a/cmds/statsd/tests/state/StateTracker_test.cpp
+++ b/cmds/statsd/tests/state/StateTracker_test.cpp
@@ -61,7 +61,7 @@
//// State with no primary fields - ScreenStateChanged
//std::shared_ptr<LogEvent> buildScreenEvent(int state) {
// std::shared_ptr<LogEvent> event =
-// std::make_shared<LogEvent>(android::util::SCREEN_STATE_CHANGED, 1000 /*timestamp*/);
+// std::make_shared<LogEvent>(util::SCREEN_STATE_CHANGED, 1000 /*timestamp*/);
// event->write((int32_t)state);
// event->init();
// return event;
@@ -70,7 +70,7 @@
//// State with one primary field - UidProcessStateChanged
//std::shared_ptr<LogEvent> buildUidProcessEvent(int uid, int state) {
// std::shared_ptr<LogEvent> event =
-// std::make_shared<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, 1000 /*timestamp*/);
+// std::make_shared<LogEvent>(util::UID_PROCESS_STATE_CHANGED, 1000 /*timestamp*/);
// event->write((int32_t)uid);
// event->write((int32_t)state);
// event->init();
@@ -85,7 +85,7 @@
// attr.set_uid(uid);
//
// std::shared_ptr<LogEvent> event =
-// std::make_shared<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, 1000 /* timestamp */);
+// std::make_shared<LogEvent>(util::WAKELOCK_STATE_CHANGED, 1000 /* timestamp */);
// event->write(chain);
// event->write((int32_t)1); // PARTIAL_WAKE_LOCK
// event->write(tag);
@@ -97,7 +97,7 @@
//// State with multiple primary fields - OverlayStateChanged
//std::shared_ptr<LogEvent> buildOverlayEvent(int uid, const std::string& packageName, int state) {
// std::shared_ptr<LogEvent> event =
-// std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
+// std::make_shared<LogEvent>(util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
// event->write((int32_t)uid);
// event->write(packageName);
// event->write(true); // using_alert_window
@@ -109,7 +109,7 @@
//// Incorrect event - missing fields
//std::shared_ptr<LogEvent> buildIncorrectOverlayEvent(int uid, const std::string& packageName, int state) {
// std::shared_ptr<LogEvent> event =
-// std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
+// std::make_shared<LogEvent>(util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
// event->write((int32_t)uid);
// event->write(packageName);
// event->write((int32_t)state);
@@ -120,7 +120,7 @@
//// Incorrect event - exclusive state has wrong type
//std::shared_ptr<LogEvent> buildOverlayEventBadStateType(int uid, const std::string& packageName) {
// std::shared_ptr<LogEvent> event =
-// std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
+// std::make_shared<LogEvent>(util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
// event->write((int32_t)uid);
// event->write(packageName);
// event->write(true);
@@ -136,7 +136,7 @@
// attr.set_uid(uid);
//
// std::shared_ptr<LogEvent> event =
-// std::make_shared<LogEvent>(android::util::BLE_SCAN_STATE_CHANGED, 1000);
+// std::make_shared<LogEvent>(util::BLE_SCAN_STATE_CHANGED, 1000);
// event->write(chain);
// event->write(reset ? 2 : acquire ? 1 : 0); // PARTIAL_WAKE_LOCK
// event->write(0); // filtered
@@ -216,7 +216,7 @@
StateManager& mgr = StateManager::getInstance();
mgr.clear();
- mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
+ mgr.registerListener(util::SCREEN_STATE_CHANGED, listener1);
EXPECT_EQ(1, mgr.getStateTrackersCount());
EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
}
@@ -236,22 +236,22 @@
// Register listener to non-existing StateTracker
EXPECT_EQ(0, mgr.getStateTrackersCount());
- EXPECT_TRUE(mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1));
+ EXPECT_TRUE(mgr.registerListener(util::SCREEN_STATE_CHANGED, listener1));
EXPECT_EQ(1, mgr.getStateTrackersCount());
- EXPECT_EQ(1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
+ EXPECT_EQ(1, mgr.getListenersCount(util::SCREEN_STATE_CHANGED));
// Register listener to existing StateTracker
- EXPECT_TRUE(mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener2));
+ EXPECT_TRUE(mgr.registerListener(util::SCREEN_STATE_CHANGED, listener2));
EXPECT_EQ(1, mgr.getStateTrackersCount());
- EXPECT_EQ(2, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
+ EXPECT_EQ(2, mgr.getListenersCount(util::SCREEN_STATE_CHANGED));
// Register already registered listener to existing StateTracker
- EXPECT_TRUE(mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener2));
+ EXPECT_TRUE(mgr.registerListener(util::SCREEN_STATE_CHANGED, listener2));
EXPECT_EQ(1, mgr.getStateTrackersCount());
- EXPECT_EQ(2, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
+ EXPECT_EQ(2, mgr.getListenersCount(util::SCREEN_STATE_CHANGED));
// Register listener to non-state atom
- EXPECT_FALSE(mgr.registerListener(android::util::BATTERY_LEVEL_CHANGED, listener2));
+ EXPECT_FALSE(mgr.registerListener(util::BATTERY_LEVEL_CHANGED, listener2));
EXPECT_EQ(1, mgr.getStateTrackersCount());
}
@@ -270,28 +270,28 @@
// Unregister listener from non-existing StateTracker
EXPECT_EQ(0, mgr.getStateTrackersCount());
- mgr.unregisterListener(android::util::SCREEN_STATE_CHANGED, listener1);
+ mgr.unregisterListener(util::SCREEN_STATE_CHANGED, listener1);
EXPECT_EQ(0, mgr.getStateTrackersCount());
- EXPECT_EQ(-1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
+ EXPECT_EQ(-1, mgr.getListenersCount(util::SCREEN_STATE_CHANGED));
// Unregister non-registered listener from existing StateTracker
- mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
+ mgr.registerListener(util::SCREEN_STATE_CHANGED, listener1);
EXPECT_EQ(1, mgr.getStateTrackersCount());
- EXPECT_EQ(1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
- mgr.unregisterListener(android::util::SCREEN_STATE_CHANGED, listener2);
+ EXPECT_EQ(1, mgr.getListenersCount(util::SCREEN_STATE_CHANGED));
+ mgr.unregisterListener(util::SCREEN_STATE_CHANGED, listener2);
EXPECT_EQ(1, mgr.getStateTrackersCount());
- EXPECT_EQ(1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
+ EXPECT_EQ(1, mgr.getListenersCount(util::SCREEN_STATE_CHANGED));
// Unregister second-to-last listener from StateTracker
- mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener2);
- mgr.unregisterListener(android::util::SCREEN_STATE_CHANGED, listener1);
+ mgr.registerListener(util::SCREEN_STATE_CHANGED, listener2);
+ mgr.unregisterListener(util::SCREEN_STATE_CHANGED, listener1);
EXPECT_EQ(1, mgr.getStateTrackersCount());
- EXPECT_EQ(1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
+ EXPECT_EQ(1, mgr.getListenersCount(util::SCREEN_STATE_CHANGED));
// Unregister last listener from StateTracker
- mgr.unregisterListener(android::util::SCREEN_STATE_CHANGED, listener2);
+ mgr.unregisterListener(util::SCREEN_STATE_CHANGED, listener2);
EXPECT_EQ(0, mgr.getStateTrackersCount());
- EXPECT_EQ(-1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
+ EXPECT_EQ(-1, mgr.getListenersCount(util::SCREEN_STATE_CHANGED));
}
// TODO(b/149590301): Update these tests to use new socket schema.
///**
@@ -305,7 +305,7 @@
//TEST(StateTrackerTest, TestStateChangeNested) {
// sp<TestStateListener> listener = new TestStateListener();
// StateManager mgr;
-// mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener);
+// mgr.registerListener(util::WAKELOCK_STATE_CHANGED, listener);
//
// std::shared_ptr<LogEvent> event1 =
// buildPartialWakelockEvent(1000 /* uid */, "tag", true /*acquire*/);
@@ -342,7 +342,7 @@
//TEST(StateTrackerTest, TestStateChangeReset) {
// sp<TestStateListener> listener = new TestStateListener();
// StateManager mgr;
-// mgr.registerListener(android::util::BLE_SCAN_STATE_CHANGED, listener);
+// mgr.registerListener(util::BLE_SCAN_STATE_CHANGED, listener);
//
// std::shared_ptr<LogEvent> event1 =
// buildBleScanEvent(1000 /* uid */, true /*acquire*/, false /*reset*/);
@@ -375,7 +375,7 @@
//TEST(StateTrackerTest, TestStateChangeNoPrimaryFields) {
// sp<TestStateListener> listener1 = new TestStateListener();
// StateManager mgr;
-// mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
+// mgr.registerListener(util::SCREEN_STATE_CHANGED, listener1);
//
// // log event
// std::shared_ptr<LogEvent> event =
@@ -390,7 +390,7 @@
// // check StateTracker was updated by querying for state
// HashableDimensionKey queryKey = DEFAULT_DIMENSION_KEY;
// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-// getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, queryKey));
+// getStateInt(mgr, util::SCREEN_STATE_CHANGED, queryKey));
//}
//
///**
@@ -400,7 +400,7 @@
//TEST(StateTrackerTest, TestStateChangeOnePrimaryField) {
// sp<TestStateListener> listener1 = new TestStateListener();
// StateManager mgr;
-// mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener1);
+// mgr.registerListener(util::UID_PROCESS_STATE_CHANGED, listener1);
//
// // log event
// std::shared_ptr<LogEvent> event =
@@ -416,13 +416,13 @@
// HashableDimensionKey queryKey;
// getUidProcessKey(1000 /* uid */, &queryKey);
// EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
-// getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey));
+// getStateInt(mgr, util::UID_PROCESS_STATE_CHANGED, queryKey));
//}
//
//TEST(StateTrackerTest, TestStateChangePrimaryFieldAttrChain) {
// sp<TestStateListener> listener1 = new TestStateListener();
// StateManager mgr;
-// mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener1);
+// mgr.registerListener(util::WAKELOCK_STATE_CHANGED, listener1);
//
// // Log event.
// std::shared_ptr<LogEvent> event =
@@ -430,7 +430,7 @@
// mgr.onLogEvent(*event);
//
// EXPECT_EQ(1, mgr.getStateTrackersCount());
-// EXPECT_EQ(1, mgr.getListenersCount(android::util::WAKELOCK_STATE_CHANGED));
+// EXPECT_EQ(1, mgr.getListenersCount(util::WAKELOCK_STATE_CHANGED));
//
// // Check listener was updated.
// EXPECT_EQ(1, listener1->updates.size());
@@ -444,19 +444,19 @@
// HashableDimensionKey queryKey;
// getPartialWakelockKey(1001 /* uid */, "tag1", &queryKey);
// EXPECT_EQ(WakelockStateChanged::ACQUIRE,
-// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey));
+// getStateInt(mgr, util::WAKELOCK_STATE_CHANGED, queryKey));
//
// // No state stored for this query key.
// HashableDimensionKey queryKey2;
// getPartialWakelockKey(1002 /* uid */, "tag1", &queryKey2);
// EXPECT_EQ(WakelockStateChanged::RELEASE,
-// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey2));
+// getStateInt(mgr, util::WAKELOCK_STATE_CHANGED, queryKey2));
//
// // Partial query fails.
// HashableDimensionKey queryKey3;
// getPartialWakelockKey(1001 /* uid */, &queryKey3);
// EXPECT_EQ(WakelockStateChanged::RELEASE,
-// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey3));
+// getStateInt(mgr, util::WAKELOCK_STATE_CHANGED, queryKey3));
//}
//
///**
@@ -466,7 +466,7 @@
//TEST(StateTrackerTest, TestStateChangeMultiplePrimaryFields) {
// sp<TestStateListener> listener1 = new TestStateListener();
// StateManager mgr;
-// mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
+// mgr.registerListener(util::OVERLAY_STATE_CHANGED, listener1);
//
// // log event
// std::shared_ptr<LogEvent> event =
@@ -482,7 +482,7 @@
// HashableDimensionKey queryKey;
// getOverlayKey(1000 /* uid */, "package1", &queryKey);
// EXPECT_EQ(OverlayStateChanged::ENTERED,
-// getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey));
+// getStateInt(mgr, util::OVERLAY_STATE_CHANGED, queryKey));
//}
//
///**
@@ -493,7 +493,7 @@
//TEST(StateTrackerTest, TestStateChangeEventError) {
// sp<TestStateListener> listener1 = new TestStateListener();
// StateManager mgr;
-// mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
+// mgr.registerListener(util::OVERLAY_STATE_CHANGED, listener1);
//
// // log event
// std::shared_ptr<LogEvent> event1 =
@@ -513,10 +513,10 @@
// sp<TestStateListener> listener3 = new TestStateListener();
// sp<TestStateListener> listener4 = new TestStateListener();
// StateManager mgr;
-// mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
-// mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener2);
-// mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener3);
-// mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener4);
+// mgr.registerListener(util::SCREEN_STATE_CHANGED, listener1);
+// mgr.registerListener(util::UID_PROCESS_STATE_CHANGED, listener2);
+// mgr.registerListener(util::OVERLAY_STATE_CHANGED, listener3);
+// mgr.registerListener(util::WAKELOCK_STATE_CHANGED, listener4);
//
// std::shared_ptr<LogEvent> event1 = buildUidProcessEvent(
// 1000,
@@ -554,40 +554,40 @@
// HashableDimensionKey queryKey1;
// getUidProcessKey(1001, &queryKey1);
// EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
-// getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
+// getStateInt(mgr, util::UID_PROCESS_STATE_CHANGED, queryKey1));
//
// // Query for UidProcessState of uid 1004 - not in state map
// HashableDimensionKey queryKey2;
// getUidProcessKey(1004, &queryKey2);
-// EXPECT_EQ(-1, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED,
+// EXPECT_EQ(-1, getStateInt(mgr, util::UID_PROCESS_STATE_CHANGED,
// queryKey2)); // default state
//
// // Query for UidProcessState of uid 1001 - after change in state
// mgr.onLogEvent(*event4);
// EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
-// getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
+// getStateInt(mgr, util::UID_PROCESS_STATE_CHANGED, queryKey1));
//
// // Query for ScreenState
// EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-// getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY));
+// getStateInt(mgr, util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY));
//
// // Query for OverlayState of uid 1000, package name "package2"
// HashableDimensionKey queryKey3;
// getOverlayKey(1000, "package2", &queryKey3);
// EXPECT_EQ(OverlayStateChanged::EXITED,
-// getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey3));
+// getStateInt(mgr, util::OVERLAY_STATE_CHANGED, queryKey3));
//
// // Query for WakelockState of uid 1005, tag 2
// HashableDimensionKey queryKey4;
// getPartialWakelockKey(1005, "tag2", &queryKey4);
// EXPECT_EQ(WakelockStateChanged::RELEASE,
-// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey4));
+// getStateInt(mgr, util::WAKELOCK_STATE_CHANGED, queryKey4));
//
// // Query for WakelockState of uid 1005, tag 1
// HashableDimensionKey queryKey5;
// getPartialWakelockKey(1005, "tag1", &queryKey5);
// EXPECT_EQ(WakelockStateChanged::ACQUIRE,
-// getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey5));
+// getStateInt(mgr, util::WAKELOCK_STATE_CHANGED, queryKey5));
//}
} // namespace statsd
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index e2eee03..050dbf8 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -51,7 +51,7 @@
}
AtomMatcher CreateTemperatureAtomMatcher() {
- return CreateSimpleAtomMatcher("TemperatureMatcher", android::util::TEMPERATURE);
+ return CreateSimpleAtomMatcher("TemperatureMatcher", util::TEMPERATURE);
}
AtomMatcher CreateScheduledJobStateChangedAtomMatcher(const string& name,
@@ -59,7 +59,7 @@
AtomMatcher atom_matcher;
atom_matcher.set_id(StringToId(name));
auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
- simple_atom_matcher->set_atom_id(android::util::SCHEDULED_JOB_STATE_CHANGED);
+ simple_atom_matcher->set_atom_id(util::SCHEDULED_JOB_STATE_CHANGED);
auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
field_value_matcher->set_field(3); // State field.
field_value_matcher->set_eq_int(state);
@@ -80,7 +80,7 @@
AtomMatcher atom_matcher;
atom_matcher.set_id(StringToId("ScreenBrightnessChanged"));
auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
- simple_atom_matcher->set_atom_id(android::util::SCREEN_BRIGHTNESS_CHANGED);
+ simple_atom_matcher->set_atom_id(util::SCREEN_BRIGHTNESS_CHANGED);
return atom_matcher;
}
@@ -88,7 +88,7 @@
AtomMatcher atom_matcher;
atom_matcher.set_id(StringToId("UidProcessStateChanged"));
auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
- simple_atom_matcher->set_atom_id(android::util::UID_PROCESS_STATE_CHANGED);
+ simple_atom_matcher->set_atom_id(util::UID_PROCESS_STATE_CHANGED);
return atom_matcher;
}
@@ -97,7 +97,7 @@
AtomMatcher atom_matcher;
atom_matcher.set_id(StringToId(name));
auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
- simple_atom_matcher->set_atom_id(android::util::WAKELOCK_STATE_CHANGED);
+ simple_atom_matcher->set_atom_id(util::WAKELOCK_STATE_CHANGED);
auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
field_value_matcher->set_field(4); // State field.
field_value_matcher->set_eq_int(state);
@@ -117,7 +117,7 @@
AtomMatcher atom_matcher;
atom_matcher.set_id(StringToId(name));
auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
- simple_atom_matcher->set_atom_id(android::util::BATTERY_SAVER_MODE_STATE_CHANGED);
+ simple_atom_matcher->set_atom_id(util::BATTERY_SAVER_MODE_STATE_CHANGED);
auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
field_value_matcher->set_field(1); // State field.
field_value_matcher->set_eq_int(state);
@@ -141,7 +141,7 @@
AtomMatcher atom_matcher;
atom_matcher.set_id(StringToId(name));
auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
- simple_atom_matcher->set_atom_id(android::util::SCREEN_STATE_CHANGED);
+ simple_atom_matcher->set_atom_id(util::SCREEN_STATE_CHANGED);
auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
field_value_matcher->set_field(1); // State field.
field_value_matcher->set_eq_int(state);
@@ -164,7 +164,7 @@
AtomMatcher atom_matcher;
atom_matcher.set_id(StringToId(name));
auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
- simple_atom_matcher->set_atom_id(android::util::SYNC_STATE_CHANGED);
+ simple_atom_matcher->set_atom_id(util::SYNC_STATE_CHANGED);
auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
field_value_matcher->set_field(3); // State field.
field_value_matcher->set_eq_int(state);
@@ -184,7 +184,7 @@
AtomMatcher atom_matcher;
atom_matcher.set_id(StringToId(name));
auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
- simple_atom_matcher->set_atom_id(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
+ simple_atom_matcher->set_atom_id(util::ACTIVITY_FOREGROUND_STATE_CHANGED);
auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
field_value_matcher->set_field(4); // Activity field.
field_value_matcher->set_eq_int(state);
@@ -206,7 +206,7 @@
AtomMatcher atom_matcher;
atom_matcher.set_id(StringToId(name));
auto simple_atom_matcher = atom_matcher.mutable_simple_atom_matcher();
- simple_atom_matcher->set_atom_id(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+ simple_atom_matcher->set_atom_id(util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
auto field_value_matcher = simple_atom_matcher->add_field_value_matcher();
field_value_matcher->set_field(3); // Process state field.
field_value_matcher->set_eq_int(state);
@@ -277,28 +277,28 @@
State CreateScreenState() {
State state;
state.set_id(StringToId("ScreenState"));
- state.set_atom_id(android::util::SCREEN_STATE_CHANGED);
+ state.set_atom_id(util::SCREEN_STATE_CHANGED);
return state;
}
State CreateUidProcessState() {
State state;
state.set_id(StringToId("UidProcessState"));
- state.set_atom_id(android::util::UID_PROCESS_STATE_CHANGED);
+ state.set_atom_id(util::UID_PROCESS_STATE_CHANGED);
return state;
}
State CreateOverlayState() {
State state;
state.set_id(StringToId("OverlayState"));
- state.set_atom_id(android::util::OVERLAY_STATE_CHANGED);
+ state.set_atom_id(util::OVERLAY_STATE_CHANGED);
return state;
}
State CreateScreenStateWithOnOffMap() {
State state;
state.set_id(StringToId("ScreenStateOnOff"));
- state.set_atom_id(android::util::SCREEN_STATE_CHANGED);
+ state.set_atom_id(util::SCREEN_STATE_CHANGED);
auto map = CreateScreenStateOnOffMap();
*state.mutable_map() = map;
@@ -309,7 +309,7 @@
State CreateScreenStateWithInDozeMap() {
State state;
state.set_id(StringToId("ScreenStateInDoze"));
- state.set_atom_id(android::util::SCREEN_STATE_CHANGED);
+ state.set_atom_id(util::SCREEN_STATE_CHANGED);
auto map = CreateScreenStateInDozeMap();
*state.mutable_map() = map;
@@ -410,10 +410,131 @@
return dimensions;
}
+shared_ptr<LogEvent> CreateTwoValueLogEvent(int atomId, int64_t eventTimeNs, int32_t value1,
+ int32_t value2) {
+ AStatsEvent* statsEvent = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(statsEvent, atomId);
+ AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs);
+
+ AStatsEvent_writeInt32(statsEvent, value1);
+ AStatsEvent_writeInt32(statsEvent, value2);
+ AStatsEvent_build(statsEvent);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+ shared_ptr<LogEvent> logEvent = std::make_shared<LogEvent>(/*uid=*/0, /*pid=*/0);
+ logEvent->parseBuffer(buf, size);
+ AStatsEvent_release(statsEvent);
+
+ return logEvent;
+}
+//
+void CreateTwoValueLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs, int32_t value1,
+ int32_t value2) {
+ AStatsEvent* statsEvent = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(statsEvent, atomId);
+ AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs);
+
+ AStatsEvent_writeInt32(statsEvent, value1);
+ AStatsEvent_writeInt32(statsEvent, value2);
+ AStatsEvent_build(statsEvent);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+ logEvent->parseBuffer(buf, size);
+ AStatsEvent_release(statsEvent);
+}
+
+shared_ptr<LogEvent> CreateThreeValueLogEvent(int atomId, int64_t eventTimeNs, int32_t value1,
+ int32_t value2, int32_t value3) {
+ AStatsEvent* statsEvent = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(statsEvent, atomId);
+ AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs);
+
+ AStatsEvent_writeInt32(statsEvent, value1);
+ AStatsEvent_writeInt32(statsEvent, value2);
+ AStatsEvent_writeInt32(statsEvent, value3);
+ AStatsEvent_build(statsEvent);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+ shared_ptr<LogEvent> logEvent = std::make_shared<LogEvent>(/*uid=*/0, /*pid=*/0);
+ logEvent->parseBuffer(buf, size);
+ AStatsEvent_release(statsEvent);
+
+ return logEvent;
+}
+
+void CreateThreeValueLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs, int32_t value1,
+ int32_t value2, int32_t value3) {
+ AStatsEvent* statsEvent = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(statsEvent, atomId);
+ AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs);
+
+ AStatsEvent_writeInt32(statsEvent, value1);
+ AStatsEvent_writeInt32(statsEvent, value2);
+ AStatsEvent_writeInt32(statsEvent, value3);
+ AStatsEvent_build(statsEvent);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+ logEvent->parseBuffer(buf, size);
+ AStatsEvent_release(statsEvent);
+}
+
+shared_ptr<LogEvent> CreateRepeatedValueLogEvent(int atomId, int64_t eventTimeNs, int32_t value) {
+ AStatsEvent* statsEvent = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(statsEvent, atomId);
+ AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs);
+
+ AStatsEvent_writeInt32(statsEvent, value);
+ AStatsEvent_writeInt32(statsEvent, value);
+ AStatsEvent_build(statsEvent);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+ shared_ptr<LogEvent> logEvent = std::make_shared<LogEvent>(/*uid=*/0, /*pid=*/0);
+ logEvent->parseBuffer(buf, size);
+ AStatsEvent_release(statsEvent);
+
+ return logEvent;
+}
+
+void CreateRepeatedValueLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs,
+ int32_t value) {
+ AStatsEvent* statsEvent = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(statsEvent, atomId);
+ AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs);
+
+ AStatsEvent_writeInt32(statsEvent, value);
+ AStatsEvent_writeInt32(statsEvent, value);
+ AStatsEvent_build(statsEvent);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+ logEvent->parseBuffer(buf, size);
+ AStatsEvent_release(statsEvent);
+}
+
+shared_ptr<LogEvent> CreateNoValuesLogEvent(int atomId, int64_t eventTimeNs) {
+ AStatsEvent* statsEvent = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(statsEvent, atomId);
+ AStatsEvent_overwriteTimestamp(statsEvent, eventTimeNs);
+ AStatsEvent_build(statsEvent);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+ shared_ptr<LogEvent> logEvent = std::make_shared<LogEvent>(/*uid=*/0, /*pid=*/0);
+ logEvent->parseBuffer(buf, size);
+ AStatsEvent_release(statsEvent);
+
+ return logEvent;
+}
+
std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
uint64_t timestampNs, const android::view::DisplayStateEnum state) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
- AStatsEvent_setAtomId(statsEvent, android::util::SCREEN_STATE_CHANGED);
+ AStatsEvent_setAtomId(statsEvent, util::SCREEN_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, state);
@@ -430,7 +551,7 @@
std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
- AStatsEvent_setAtomId(statsEvent, android::util::BATTERY_SAVER_MODE_STATE_CHANGED);
+ AStatsEvent_setAtomId(statsEvent, util::BATTERY_SAVER_MODE_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, BatterySaverModeStateChanged::ON);
@@ -447,7 +568,7 @@
std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
- AStatsEvent_setAtomId(statsEvent, android::util::BATTERY_SAVER_MODE_STATE_CHANGED);
+ AStatsEvent_setAtomId(statsEvent, util::BATTERY_SAVER_MODE_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, BatterySaverModeStateChanged::OFF);
@@ -464,7 +585,7 @@
std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(uint64_t timestampNs, int level) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
- AStatsEvent_setAtomId(statsEvent, android::util::SCREEN_BRIGHTNESS_CHANGED);
+ AStatsEvent_setAtomId(statsEvent, util::SCREEN_BRIGHTNESS_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, level);
@@ -482,7 +603,7 @@
//std::unique_ptr<LogEvent> CreateScheduledJobStateChangedEvent(
// const std::vector<AttributionNodeInternal>& attributions, const string& jobName,
// const ScheduledJobStateChanged::State state, uint64_t timestampNs) {
-// auto event = std::make_unique<LogEvent>(android::util::SCHEDULED_JOB_STATE_CHANGED, timestampNs);
+// auto event = std::make_unique<LogEvent>(util::SCHEDULED_JOB_STATE_CHANGED, timestampNs);
// event->write(attributions);
// event->write(jobName);
// event->write(state);
@@ -511,7 +632,7 @@
const string& wakelockName,
const WakelockStateChanged::State state) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
- AStatsEvent_setAtomId(statsEvent, android::util::WAKELOCK_STATE_CHANGED);
+ AStatsEvent_setAtomId(statsEvent, util::WAKELOCK_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
vector<const char*> cTags(attributionTags.size());
@@ -555,7 +676,7 @@
std::unique_ptr<LogEvent> CreateActivityForegroundStateChangedEvent(
uint64_t timestampNs, const int uid, const ActivityForegroundStateChanged::State state) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
- AStatsEvent_setAtomId(statsEvent, android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
+ AStatsEvent_setAtomId(statsEvent, util::ACTIVITY_FOREGROUND_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, uid);
@@ -589,7 +710,7 @@
const string& name,
const SyncStateChanged::State state) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
- AStatsEvent_setAtomId(statsEvent, android::util::SYNC_STATE_CHANGED);
+ AStatsEvent_setAtomId(statsEvent, util::SYNC_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
vector<const char*> cTags(attributionTags.size());
@@ -632,7 +753,7 @@
std::unique_ptr<LogEvent> CreateProcessLifeCycleStateChangedEvent(
uint64_t timestampNs, const int uid, const ProcessLifeCycleStateChanged::State state) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
- AStatsEvent_setAtomId(statsEvent, android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+ AStatsEvent_setAtomId(statsEvent, util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, uid);
@@ -656,7 +777,7 @@
std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(uint64_t timestampNs, const int uid) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
- AStatsEvent_setAtomId(statsEvent, android::util::APP_CRASH_OCCURRED);
+ AStatsEvent_setAtomId(statsEvent, util::APP_CRASH_OCCURRED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, uid);
@@ -676,7 +797,7 @@
std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(uint64_t timestampNs, int hostUid,
int isolatedUid, bool is_create) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
- AStatsEvent_setAtomId(statsEvent, android::util::ISOLATED_UID_CHANGED);
+ AStatsEvent_setAtomId(statsEvent, util::ISOLATED_UID_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, hostUid);
@@ -696,7 +817,7 @@
std::unique_ptr<LogEvent> CreateUidProcessStateChangedEvent(
uint64_t timestampNs, int uid, const android::app::ProcessStateEnum state) {
AStatsEvent* statsEvent = AStatsEvent_obtain();
- AStatsEvent_setAtomId(statsEvent, android::util::UID_PROCESS_STATE_CHANGED);
+ AStatsEvent_setAtomId(statsEvent, util::UID_PROCESS_STATE_CHANGED);
AStatsEvent_overwriteTimestamp(statsEvent, timestampNs);
AStatsEvent_writeInt32(statsEvent, uid);
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index 4371015..ead041c 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -25,7 +25,7 @@
#include "src/hash.h"
#include "src/logd/LogEvent.h"
#include "src/stats_log_util.h"
-#include "statslog.h"
+#include "statslog_statsdtest.h"
namespace android {
namespace os {
@@ -38,8 +38,8 @@
using google::protobuf::RepeatedPtrField;
using Status = ::ndk::ScopedAStatus;
-const int SCREEN_STATE_ATOM_ID = android::util::SCREEN_STATE_CHANGED;
-const int UID_PROCESS_STATE_ATOM_ID = android::util::UID_PROCESS_STATE_CHANGED;
+const int SCREEN_STATE_ATOM_ID = util::SCREEN_STATE_CHANGED;
+const int UID_PROCESS_STATE_ATOM_ID = util::UID_PROCESS_STATE_CHANGED;
// Converts a ProtoOutputStream to a StatsLogReport proto.
StatsLogReport outputStreamToProto(ProtoOutputStream* proto);
@@ -164,6 +164,29 @@
FieldMatcher CreateAttributionUidDimensions(const int atomId,
const std::vector<Position>& positions);
+shared_ptr<LogEvent> CreateTwoValueLogEvent(int atomId, int64_t eventTimeNs, int32_t value1,
+ int32_t value2);
+
+void CreateTwoValueLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs, int32_t value1,
+ int32_t value2);
+
+shared_ptr<LogEvent> CreateThreeValueLogEvent(int atomId, int64_t eventTimeNs, int32_t value1,
+ int32_t value2, int32_t value3);
+
+void CreateThreeValueLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs, int32_t value1,
+ int32_t value2, int32_t value3);
+
+// The repeated value log event helpers create a log event with two int fields, both
+// set to the same value. This is useful for testing metrics that are only interested
+// in the value of the second field but still need the first field to be populated.
+std::shared_ptr<LogEvent> CreateRepeatedValueLogEvent(int atomId, int64_t eventTimeNs,
+ int32_t value);
+
+void CreateRepeatedValueLogEvent(LogEvent* logEvent, int atomId, int64_t eventTimeNs,
+ int32_t value);
+
+std::shared_ptr<LogEvent> CreateNoValuesLogEvent(int atomId, int64_t eventTimeNs);
+
// Create log event for screen state changed.
std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
uint64_t timestampNs, const android::view::DisplayStateEnum state);
diff --git a/config/hiddenapi-greylist-max-q.txt b/config/hiddenapi-greylist-max-q.txt
index a895a44..4832dd1 100644
--- a/config/hiddenapi-greylist-max-q.txt
+++ b/config/hiddenapi-greylist-max-q.txt
@@ -406,7 +406,6 @@
Lcom/android/internal/R$string;->enable_explore_by_touch_warning_title:I
Lcom/android/internal/R$string;->gigabyteShort:I
Lcom/android/internal/R$string;->kilobyteShort:I
-Lcom/android/internal/R$string;->map:I
Lcom/android/internal/R$string;->megabyteShort:I
Lcom/android/internal/R$string;->notification_title:I
Lcom/android/internal/R$string;->no_matches:I
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 1a92b75..b3a0be1 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1315,7 +1315,8 @@
/**
* @return The in-memory or loaded icon that represents the current state of this task.
- * @deprecated This call is no longer supported.
+ * @deprecated This call is no longer supported. The caller should keep track of any icons
+ * it sets for the task descriptions internally.
*/
@Deprecated
public Bitmap getIcon() {
@@ -3627,11 +3628,40 @@
}
}
+ /**
+ * Set custom state data for this process. It will be included in the record of
+ * {@link ApplicationExitInfo} on the death of the current calling process; the new process
+ * of the app can retrieve this state data by calling
+ * {@link ApplicationExitInfo#getProcessStateSummary} on the record returned by
+ * {@link #getHistoricalProcessExitReasons}.
+ *
+ * <p> This would be useful for the calling app to save its stateful data: if it's
+ * killed later for any reason, the new process of the app can know what the
+ * previous process of the app was doing. For instance, you could use this to encode
+ * the current level in a game, or a set of features/experiments that were enabled. Later you
+ * could analyze under what circumstances the app tends to crash or use too much memory.
+ * However, it's not suggested to rely on this to restore the applications previous UI state
+ * or so, it's only meant for analyzing application healthy status.</p>
+ *
+ * <p> System might decide to throttle the calls to this API; so call this API in a reasonable
+ * manner, excessive calls to this API could result a {@link java.lang.RuntimeException}.
+ * </p>
+ *
+ * @param state The state data
+ */
+ public void setProcessStateSummary(@Nullable byte[] state) {
+ try {
+ getService().setProcessStateSummary(state);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/*
* @return Whether or not the low memory kill will be reported in
* {@link #getHistoricalProcessExitReasons}.
*
- * @see {@link ApplicationExitInfo#REASON_LOW_MEMORY}
+ * @see ApplicationExitInfo#REASON_LOW_MEMORY
*/
public static boolean isLowMemoryKillReportSupported() {
return SystemProperties.getBoolean("persist.sys.lmk.reportkills", false);
@@ -4242,8 +4272,6 @@
* {@code false} otherwise.
* @hide
*/
- @SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION)
public boolean updateMccMncConfiguration(@NonNull String mcc, @NonNull String mnc) {
if (mcc == null || mnc == null) {
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 489a0de..f926075 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -248,7 +248,8 @@
/**
* Returns whether the given user requires credential entry at this time. This is used to
- * intercept activity launches for work apps when the Work Challenge is present.
+ * intercept activity launches for locked work apps due to work challenge being triggered or
+ * when the profile user is yet to be unlocked.
*/
public abstract boolean shouldConfirmCredentials(@UserIdInt int userId);
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 4aacf48..7fd02112 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -209,6 +209,12 @@
"android.activity.pendingIntentLaunchFlags";
/**
+ * See {@link #setTaskAlwaysOnTop}.
+ * @hide
+ */
+ private static final String KEY_TASK_ALWAYS_ON_TOP = "android.activity.alwaysOnTop";
+
+ /**
* See {@link #setTaskOverlay}.
* @hide
*/
@@ -337,6 +343,7 @@
private int mSplitScreenCreateMode = SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
private boolean mLockTaskMode = false;
private boolean mDisallowEnterPictureInPictureWhileLaunching;
+ private boolean mTaskAlwaysOnTop;
private boolean mTaskOverlay;
private boolean mTaskOverlayCanResume;
private boolean mAvoidMoveToFront;
@@ -971,6 +978,7 @@
mLaunchActivityType = opts.getInt(KEY_LAUNCH_ACTIVITY_TYPE, ACTIVITY_TYPE_UNDEFINED);
mLaunchTaskId = opts.getInt(KEY_LAUNCH_TASK_ID, -1);
mPendingIntentLaunchFlags = opts.getInt(KEY_PENDING_INTENT_LAUNCH_FLAGS, 0);
+ mTaskAlwaysOnTop = opts.getBoolean(KEY_TASK_ALWAYS_ON_TOP, false);
mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false);
mTaskOverlayCanResume = opts.getBoolean(KEY_TASK_OVERLAY_CAN_RESUME, false);
mAvoidMoveToFront = opts.getBoolean(KEY_AVOID_MOVE_TO_FRONT, false);
@@ -1300,6 +1308,22 @@
}
/**
+ * Set's whether the task for the activity launched with this option should always be on top.
+ * @hide
+ */
+ @TestApi
+ public void setTaskAlwaysOnTop(boolean alwaysOnTop) {
+ mTaskAlwaysOnTop = alwaysOnTop;
+ }
+
+ /**
+ * @hide
+ */
+ public boolean getTaskAlwaysOnTop() {
+ return mTaskAlwaysOnTop;
+ }
+
+ /**
* Set's whether the activity launched with this option should be a task overlay. That is the
* activity will always be the top activity of the task.
* @param canResume {@code false} if the task will also not be moved to the front of the stack.
@@ -1556,6 +1580,9 @@
if (mPendingIntentLaunchFlags != 0) {
b.putInt(KEY_PENDING_INTENT_LAUNCH_FLAGS, mPendingIntentLaunchFlags);
}
+ if (mTaskAlwaysOnTop) {
+ b.putBoolean(KEY_TASK_ALWAYS_ON_TOP, mTaskAlwaysOnTop);
+ }
if (mTaskOverlay) {
b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay);
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index fa4aa19..9c1a861 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1386,6 +1386,7 @@
"android:auto_revoke_permissions_if_unused";
/** @hide Auto-revoke app permissions if app is unused for an extended period */
+ @SystemApi
public static final String OPSTR_AUTO_REVOKE_MANAGED_BY_INSTALLER =
"android:auto_revoke_managed_by_installer";
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index 5df3257..61be01f 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -23,7 +23,9 @@
import android.app.ActivityManager.RunningAppProcessInfo.Importance;
import android.icu.text.SimpleDateFormat;
import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.DebugUtils;
@@ -31,12 +33,17 @@
import android.util.proto.ProtoOutputStream;
import android.util.proto.WireTypeMismatchException;
+import com.android.internal.util.ArrayUtils;
+
+import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Date;
import java.util.Objects;
+import java.util.zip.GZIPInputStream;
/**
* Describes the information of an application process's death.
@@ -321,85 +328,105 @@
// be categorized in {@link #REASON_OTHER}, with subreason code starting from 1000.
/**
- * @see {@link #getPid}
+ * @see #getPid
*/
private int mPid;
/**
- * @see {@link #getRealUid}
+ * @see #getRealUid
*/
private int mRealUid;
/**
- * @see {@link #getPackageUid}
+ * @see #getPackageUid
*/
private int mPackageUid;
/**
- * @see {@link #getDefiningUid}
+ * @see #getDefiningUid
*/
private int mDefiningUid;
/**
- * @see {@link #getProcessName}
+ * @see #getProcessName
*/
private String mProcessName;
/**
- * @see {@link #getReason}
+ * @see #getReason
*/
private @Reason int mReason;
/**
- * @see {@link #getStatus}
+ * @see #getStatus
*/
private int mStatus;
/**
- * @see {@link #getImportance}
+ * @see #getImportance
*/
private @Importance int mImportance;
/**
- * @see {@link #getPss}
+ * @see #getPss
*/
private long mPss;
/**
- * @see {@link #getRss}
+ * @see #getRss
*/
private long mRss;
/**
- * @see {@link #getTimestamp}
+ * @see #getTimestamp
*/
private @CurrentTimeMillisLong long mTimestamp;
/**
- * @see {@link #getDescription}
+ * @see #getDescription
*/
private @Nullable String mDescription;
/**
- * @see {@link #getSubReason}
+ * @see #getSubReason
*/
private @SubReason int mSubReason;
/**
- * @see {@link #getConnectionGroup}
+ * @see #getConnectionGroup
*/
private int mConnectionGroup;
/**
- * @see {@link #getPackageName}
+ * @see #getPackageName
*/
private String mPackageName;
/**
- * @see {@link #getPackageList}
+ * @see #getPackageList
*/
private String[] mPackageList;
+ /**
+ * @see #getProcessStateSummary
+ */
+ private byte[] mState;
+
+ /**
+ * The file to the trace file in the storage;
+ *
+ * for system internal use only, will not retain across processes.
+ *
+ * @see #getTraceInputStream
+ */
+ private File mTraceFile;
+
+ /**
+ * The Binder interface to retrieve the file descriptor to
+ * the trace file from the system.
+ */
+ private IAppTraceRetriever mAppTraceRetriever;
+
/** @hide */
@IntDef(prefix = { "REASON_" }, value = {
REASON_UNKNOWN,
@@ -557,6 +584,54 @@
}
/**
+ * Return the state data set by calling {@link ActivityManager#setProcessStateSummary}
+ * from the process before its death.
+ *
+ * @return The process-customized data
+ * @see ActivityManager#setProcessStateSummary(byte[])
+ */
+ public @Nullable byte[] getProcessStateSummary() {
+ return mState;
+ }
+
+ /**
+ * Return the InputStream to the traces that was taken by the system
+ * prior to the death of the process; typically it'll be available when
+ * the reason is {@link #REASON_ANR}, though if the process gets an ANR
+ * but recovers, and dies for another reason later, this trace will be included
+ * in the record of {@link ApplicationExitInfo} still.
+ *
+ * @return The input stream to the traces that was taken by the system
+ * prior to the death of the process.
+ */
+ public @Nullable InputStream getTraceInputStream() throws IOException {
+ if (mAppTraceRetriever == null) {
+ return null;
+ }
+ try {
+ final ParcelFileDescriptor fd = mAppTraceRetriever.getTraceFileDescriptor(
+ mPackageName, mPackageUid, mPid);
+ if (fd == null) {
+ return null;
+ }
+ return new GZIPInputStream(new ParcelFileDescriptor.AutoCloseInputStream(fd));
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Similar to {@link #getTraceInputStream} but return the File object.
+ *
+ * For internal use only.
+ *
+ * @hide
+ */
+ public @Nullable File getTraceFile() {
+ return mTraceFile;
+ }
+
+ /**
* A subtype reason in conjunction with {@link #mReason}.
*
* For internal use only.
@@ -569,7 +644,7 @@
/**
* The connection group this process belongs to, if there is any.
- * @see {@link android.content.Context#updateServiceGroup}.
+ * @see android.content.Context#updateServiceGroup
*
* For internal use only.
*
@@ -582,8 +657,6 @@
/**
* Name of first package running in this process;
*
- * For system internal use only, will not retain across processes.
- *
* @hide
*/
public String getPackageName() {
@@ -602,7 +675,7 @@
}
/**
- * @see {@link #getPid}
+ * @see #getPid
*
* @hide
*/
@@ -611,7 +684,7 @@
}
/**
- * @see {@link #getRealUid}
+ * @see #getRealUid
*
* @hide
*/
@@ -620,7 +693,7 @@
}
/**
- * @see {@link #getPackageUid}
+ * @see #getPackageUid
*
* @hide
*/
@@ -629,7 +702,7 @@
}
/**
- * @see {@link #getDefiningUid}
+ * @see #getDefiningUid
*
* @hide
*/
@@ -638,7 +711,7 @@
}
/**
- * @see {@link #getProcessName}
+ * @see #getProcessName
*
* @hide
*/
@@ -647,7 +720,7 @@
}
/**
- * @see {@link #getReason}
+ * @see #getReason
*
* @hide
*/
@@ -656,7 +729,7 @@
}
/**
- * @see {@link #getStatus}
+ * @see #getStatus
*
* @hide
*/
@@ -665,7 +738,7 @@
}
/**
- * @see {@link #getImportance}
+ * @see #getImportance
*
* @hide
*/
@@ -674,7 +747,7 @@
}
/**
- * @see {@link #getPss}
+ * @see #getPss
*
* @hide
*/
@@ -683,7 +756,7 @@
}
/**
- * @see {@link #getRss}
+ * @see #getRss
*
* @hide
*/
@@ -692,7 +765,7 @@
}
/**
- * @see {@link #getTimestamp}
+ * @see #getTimestamp
*
* @hide
*/
@@ -701,7 +774,7 @@
}
/**
- * @see {@link #getDescription}
+ * @see #getDescription
*
* @hide
*/
@@ -710,7 +783,7 @@
}
/**
- * @see {@link #getSubReason}
+ * @see #getSubReason
*
* @hide
*/
@@ -719,7 +792,7 @@
}
/**
- * @see {@link #getConnectionGroup}
+ * @see #getConnectionGroup
*
* @hide
*/
@@ -728,7 +801,7 @@
}
/**
- * @see {@link #getPackageName}
+ * @see #getPackageName
*
* @hide
*/
@@ -737,7 +810,7 @@
}
/**
- * @see {@link #getPackageList}
+ * @see #getPackageList
*
* @hide
*/
@@ -745,6 +818,33 @@
mPackageList = packageList;
}
+ /**
+ * @see #getProcessStateSummary
+ *
+ * @hide
+ */
+ public void setProcessStateSummary(final byte[] state) {
+ mState = state;
+ }
+
+ /**
+ * @see #getTraceFile
+ *
+ * @hide
+ */
+ public void setTraceFile(final File traceFile) {
+ mTraceFile = traceFile;
+ }
+
+ /**
+ * @see #mAppTraceRetriever
+ *
+ * @hide
+ */
+ public void setAppTraceRetriever(final IAppTraceRetriever retriever) {
+ mAppTraceRetriever = retriever;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -757,6 +857,7 @@
dest.writeInt(mPackageUid);
dest.writeInt(mDefiningUid);
dest.writeString(mProcessName);
+ dest.writeString(mPackageName);
dest.writeInt(mConnectionGroup);
dest.writeInt(mReason);
dest.writeInt(mSubReason);
@@ -766,6 +867,13 @@
dest.writeLong(mRss);
dest.writeLong(mTimestamp);
dest.writeString(mDescription);
+ dest.writeByteArray(mState);
+ if (mAppTraceRetriever != null) {
+ dest.writeInt(1);
+ dest.writeStrongBinder(mAppTraceRetriever.asBinder());
+ } else {
+ dest.writeInt(0);
+ }
}
/** @hide */
@@ -779,6 +887,7 @@
mPackageUid = other.mPackageUid;
mDefiningUid = other.mDefiningUid;
mProcessName = other.mProcessName;
+ mPackageName = other.mPackageName;
mConnectionGroup = other.mConnectionGroup;
mReason = other.mReason;
mStatus = other.mStatus;
@@ -790,6 +899,9 @@
mDescription = other.mDescription;
mPackageName = other.mPackageName;
mPackageList = other.mPackageList;
+ mState = other.mState;
+ mTraceFile = other.mTraceFile;
+ mAppTraceRetriever = other.mAppTraceRetriever;
}
private ApplicationExitInfo(@NonNull Parcel in) {
@@ -798,6 +910,7 @@
mPackageUid = in.readInt();
mDefiningUid = in.readInt();
mProcessName = in.readString();
+ mPackageName = in.readString();
mConnectionGroup = in.readInt();
mReason = in.readInt();
mSubReason = in.readInt();
@@ -807,6 +920,10 @@
mRss = in.readLong();
mTimestamp = in.readLong();
mDescription = in.readString();
+ mState = in.createByteArray();
+ if (in.readInt() == 1) {
+ mAppTraceRetriever = IAppTraceRetriever.Stub.asInterface(in.readStrongBinder());
+ }
}
public @NonNull static final Creator<ApplicationExitInfo> CREATOR =
@@ -839,6 +956,9 @@
pw.print(prefix + " pss="); DebugUtils.printSizeValue(pw, mPss << 10); pw.println();
pw.print(prefix + " rss="); DebugUtils.printSizeValue(pw, mRss << 10); pw.println();
pw.println(prefix + " description=" + mDescription);
+ pw.println(prefix + " state=" + (ArrayUtils.isEmpty(mState)
+ ? "empty" : Integer.toString(mState.length) + " bytes"));
+ pw.println(prefix + " trace=" + mTraceFile);
}
@Override
@@ -859,6 +979,9 @@
sb.append(" pss="); DebugUtils.sizeValueToString(mPss << 10, sb);
sb.append(" rss="); DebugUtils.sizeValueToString(mRss << 10, sb);
sb.append(" description=").append(mDescription);
+ sb.append(" state=").append(ArrayUtils.isEmpty(mState)
+ ? "empty" : Integer.toString(mState.length) + " bytes");
+ sb.append(" trace=").append(mTraceFile);
return sb.toString();
}
@@ -961,6 +1084,9 @@
proto.write(ApplicationExitInfoProto.RSS, mRss);
proto.write(ApplicationExitInfoProto.TIMESTAMP, mTimestamp);
proto.write(ApplicationExitInfoProto.DESCRIPTION, mDescription);
+ proto.write(ApplicationExitInfoProto.STATE, mState);
+ proto.write(ApplicationExitInfoProto.TRACE_FILE,
+ mTraceFile == null ? null : mTraceFile.getAbsolutePath());
proto.end(token);
}
@@ -1019,6 +1145,15 @@
case (int) ApplicationExitInfoProto.DESCRIPTION:
mDescription = proto.readString(ApplicationExitInfoProto.DESCRIPTION);
break;
+ case (int) ApplicationExitInfoProto.STATE:
+ mState = proto.readBytes(ApplicationExitInfoProto.STATE);
+ break;
+ case (int) ApplicationExitInfoProto.TRACE_FILE:
+ final String path = proto.readString(ApplicationExitInfoProto.TRACE_FILE);
+ if (!TextUtils.isEmpty(path)) {
+ mTraceFile = new File(path);
+ }
+ break;
}
}
proto.end(token);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 18df401..0b0a803 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -3297,15 +3297,6 @@
}
@Override
- public String[] getTelephonyPackageNames() {
- try {
- return mPM.getTelephonyPackageNames();
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
- }
- }
-
- @Override
public String getSystemCaptionsServicePackageName() {
try {
return mPM.getSystemCaptionsServicePackageName();
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 6f0611e..b8221b4 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -652,4 +652,27 @@
*/
void setActivityLocusContext(in ComponentName activity, in LocusId locusId,
in IBinder appToken);
+
+ /**
+ * Set custom state data for this process. It will be included in the record of
+ * {@link ApplicationExitInfo} on the death of the current calling process; the new process
+ * of the app can retrieve this state data by calling
+ * {@link ApplicationExitInfo#getProcessStateSummary} on the record returned by
+ * {@link #getHistoricalProcessExitReasons}.
+ *
+ * <p> This would be useful for the calling app to save its stateful data: if it's
+ * killed later for any reason, the new process of the app can know what the
+ * previous process of the app was doing. For instance, you could use this to encode
+ * the current level in a game, or a set of features/experiments that were enabled. Later you
+ * could analyze under what circumstances the app tends to crash or use too much memory.
+ * However, it's not suggested to rely on this to restore the applications previous UI state
+ * or so, it's only meant for analyzing application healthy status.</p>
+ *
+ * <p> System might decide to throttle the calls to this API; so call this API in a reasonable
+ * manner, excessive calls to this API could result a {@link java.lang.RuntimeException}.
+ * </p>
+ *
+ * @param state The customized state data
+ */
+ void setProcessStateSummary(in byte[] state);
}
diff --git a/core/java/android/app/IAppTraceRetriever.aidl b/core/java/android/app/IAppTraceRetriever.aidl
new file mode 100644
index 0000000..1463da7
--- /dev/null
+++ b/core/java/android/app/IAppTraceRetriever.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.app;
+
+import android.os.ParcelFileDescriptor;
+
+/**
+ * An interface that's to be used by {@link ApplicationExitInfo#getTraceFile()}
+ * to retrieve the actual file descriptor to its trace file.
+ *
+ * @hide
+ */
+interface IAppTraceRetriever {
+ /**
+ * Retrieve the trace file with given packageName/uid/pid.
+ *
+ * @param packagename The target package name of the trace
+ * @param uid The target UID of the trace
+ * @param pid The target PID of the trace
+ * @return The file descriptor to the trace file, or null if it's not found.
+ */
+ ParcelFileDescriptor getTraceFileDescriptor(in String packageName,
+ int uid, int pid);
+}
diff --git a/core/java/android/app/ITaskOrganizerController.aidl b/core/java/android/app/ITaskOrganizerController.aidl
index 9d6c3d6..a448e13 100644
--- a/core/java/android/app/ITaskOrganizerController.aidl
+++ b/core/java/android/app/ITaskOrganizerController.aidl
@@ -32,6 +32,11 @@
void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode);
/**
+ * Unregisters a previously registered task organizer.
+ */
+ void unregisterTaskOrganizer(ITaskOrganizer organizer);
+
+ /**
* Apply multiple WindowContainer operations at once.
* @param organizer If non-null this transaction will use the synchronization
* scheme described in BLASTSyncEngine.java. The SurfaceControl transaction
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index cbbdf63..811b9c0 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1015,14 +1015,15 @@
}
/**
+ * Returns the currently applied notification policy.
+ *
* <p>
- * Gets the currently applied notification policy. If {@link #getCurrentInterruptionFilter}
- * is equal to {@link #INTERRUPTION_FILTER_ALL}, then the consolidated notification policy
- * will match the default notification policy returned by {@link #getNotificationPolicy}.
+ * If {@link #getCurrentInterruptionFilter} is equal to {@link #INTERRUPTION_FILTER_ALL},
+ * then the consolidated notification policy will match the default notification policy
+ * returned by {@link #getNotificationPolicy}.
* </p>
*/
- @Nullable
- public NotificationManager.Policy getConsolidatedNotificationPolicy() {
+ public @NonNull NotificationManager.Policy getConsolidatedNotificationPolicy() {
INotificationManager service = getService();
try {
return service.getConsolidatedNotificationPolicy();
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 81671c3..9f5dee9 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -250,28 +250,6 @@
return dm;
}
- private static void applyNonDefaultDisplayMetricsToConfiguration(
- @NonNull DisplayMetrics dm, @NonNull Configuration config) {
- config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
- config.densityDpi = dm.densityDpi;
- config.screenWidthDp = (int) (dm.widthPixels / dm.density);
- config.screenHeightDp = (int) (dm.heightPixels / dm.density);
- int sl = Configuration.resetScreenLayout(config.screenLayout);
- if (dm.widthPixels > dm.heightPixels) {
- config.orientation = Configuration.ORIENTATION_LANDSCAPE;
- config.screenLayout = Configuration.reduceScreenLayout(sl,
- config.screenWidthDp, config.screenHeightDp);
- } else {
- config.orientation = Configuration.ORIENTATION_PORTRAIT;
- config.screenLayout = Configuration.reduceScreenLayout(sl,
- config.screenHeightDp, config.screenWidthDp);
- }
- config.smallestScreenWidthDp = Math.min(config.screenWidthDp, config.screenHeightDp);
- config.compatScreenWidthDp = config.screenWidthDp;
- config.compatScreenHeightDp = config.screenHeightDp;
- config.compatSmallestScreenWidthDp = config.smallestScreenWidthDp;
- }
-
public boolean applyCompatConfigurationLocked(int displayDensity,
@NonNull Configuration compatConfiguration) {
if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) {
@@ -519,17 +497,11 @@
private Configuration generateConfig(@NonNull ResourcesKey key, @NonNull DisplayMetrics dm) {
Configuration config;
- final boolean isDefaultDisplay = (key.mDisplayId == Display.DEFAULT_DISPLAY);
final boolean hasOverrideConfig = key.hasOverrideConfiguration();
- if (!isDefaultDisplay || hasOverrideConfig) {
+ if (hasOverrideConfig) {
config = new Configuration(getConfiguration());
- if (!isDefaultDisplay) {
- applyNonDefaultDisplayMetricsToConfiguration(dm, config);
- }
- if (hasOverrideConfig) {
- config.updateFrom(key.mOverrideConfiguration);
- if (DEBUG) Slog.v(TAG, "Applied overrideConfig=" + key.mOverrideConfiguration);
- }
+ config.updateFrom(key.mOverrideConfiguration);
+ if (DEBUG) Slog.v(TAG, "Applied overrideConfig=" + key.mOverrideConfiguration);
} else {
config = getConfiguration();
}
@@ -1110,8 +1082,6 @@
+ resourcesImpl + " config to: " + config);
}
int displayId = key.mDisplayId;
- final boolean hasOverrideConfiguration = key.hasOverrideConfiguration();
- tmpConfig.setTo(config);
// Get new DisplayMetrics based on the DisplayAdjustments given to the ResourcesImpl. Update
// a copy if the CompatibilityInfo changed, because the ResourcesImpl object will handle the
@@ -1121,15 +1091,12 @@
daj = new DisplayAdjustments(daj);
daj.setCompatibilityInfo(compat);
}
- daj.setConfiguration(config);
- DisplayMetrics dm = getDisplayMetrics(displayId, daj);
- if (displayId != Display.DEFAULT_DISPLAY) {
- applyNonDefaultDisplayMetricsToConfiguration(dm, tmpConfig);
- }
-
- if (hasOverrideConfiguration) {
+ tmpConfig.setTo(config);
+ if (key.hasOverrideConfiguration()) {
tmpConfig.updateFrom(key.mOverrideConfiguration);
}
+ daj.setConfiguration(tmpConfig);
+ DisplayMetrics dm = getDisplayMetrics(displayId, daj);
resourcesImpl.updateConfiguration(tmpConfig, dm, compat);
}
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 81396fe..dc8269f 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -34,7 +34,6 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
-import android.view.contentcapture.ContentCaptureManager;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -307,8 +306,7 @@
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.java
* bind}
*/
-public abstract class Service extends ContextWrapper implements ComponentCallbacks2,
- ContentCaptureManager.ContentCaptureClient {
+public abstract class Service extends ContextWrapper implements ComponentCallbacks2 {
private static final String TAG = "Service";
/**
@@ -819,16 +817,8 @@
writer.println("nothing to dump");
}
- @Override
- protected void attachBaseContext(Context newBase) {
- super.attachBaseContext(newBase);
- if (newBase != null) {
- newBase.setContentCaptureOptions(getContentCaptureOptions());
- }
- }
-
// ------------------ Internal API ------------------
-
+
/**
* @hide
*/
@@ -845,7 +835,6 @@
mActivityManager = (IActivityManager)activityManager;
mStartCompatibility = getApplicationInfo().targetSdkVersion
< Build.VERSION_CODES.ECLAIR;
- setContentCaptureOptions(application.getContentCaptureOptions());
}
/**
@@ -860,18 +849,6 @@
return mClassName;
}
- /** @hide */
- @Override
- public final ContentCaptureManager.ContentCaptureClient getContentCaptureClient() {
- return this;
- }
-
- /** @hide */
- @Override
- public final ComponentName contentCaptureClientGetComponentName() {
- return new ComponentName(this, mClassName);
- }
-
// set by the thread after the constructor and before onCreate(Bundle icicle) is called.
@UnsupportedAppUsage
private ActivityThread mThread = null;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index e8f30df..1aabd24 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -359,14 +359,6 @@
}
});
- registerService(Context.NETWORK_STACK_SERVICE, IBinder.class,
- new StaticServiceFetcher<IBinder>() {
- @Override
- public IBinder createService() {
- return ServiceManager.getService(Context.NETWORK_STACK_SERVICE);
- }
- });
-
registerService(Context.TETHERING_SERVICE, TetheringManager.class,
new CachedServiceFetcher<TetheringManager>() {
@Override
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 5b8ee71..37f1a65 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6832,6 +6832,10 @@
* package will no longer be suspended. The admin can block this by using
* {@link #setUninstallBlocked}.
*
+ * <p>Some apps cannot be suspended, such as device admins, the active launcher, the required
+ * package installer, the required package uninstaller, the required package verifier, the
+ * default dialer, and the permission controller.
+ *
* @param admin The name of the admin component to check, or {@code null} if the caller is a
* package access delegate.
* @param packageNames The package names to suspend or unsuspend.
@@ -11919,13 +11923,17 @@
}
/**
- * Called by device owner or profile owner of an organization-owned managed profile to return
- * whether Common Criteria mode is currently enabled for the device.
+ * Returns whether Common Criteria mode is currently enabled. Device owner and profile owner of
+ * an organization-owned managed profile can query its own Common Criteria mode setting by
+ * calling this method with its admin {@link ComponentName}. Any caller can obtain the
+ * aggregated device-wide Common Criteria mode state by passing {@code null} as the
+ * {@code admin} argument.
*
- * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+ * @param admin which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if the caller is not a device admin.
* @return {@code true} if Common Criteria mode is enabled, {@code false} otherwise.
*/
- public boolean isCommonCriteriaModeEnabled(@NonNull ComponentName admin) {
+ public boolean isCommonCriteriaModeEnabled(@Nullable ComponentName admin) {
throwIfParentInstance("isCommonCriteriaModeEnabled");
if (mService != null) {
try {
diff --git a/core/java/android/app/timezonedetector/ManualTimeZoneSuggestion.java b/core/java/android/app/timezonedetector/ManualTimeZoneSuggestion.java
index 3a9adc7..22e2efb 100644
--- a/core/java/android/app/timezonedetector/ManualTimeZoneSuggestion.java
+++ b/core/java/android/app/timezonedetector/ManualTimeZoneSuggestion.java
@@ -20,7 +20,9 @@
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.ShellCommand;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -127,4 +129,32 @@
+ ", mDebugInfo=" + mDebugInfo
+ '}';
}
+
+ /** @hide */
+ public static ManualTimeZoneSuggestion parseCommandLineArg(@NonNull ShellCommand cmd) {
+ String zoneId = null;
+ String opt;
+ while ((opt = cmd.getNextArg()) != null) {
+ switch (opt) {
+ case "--zone_id": {
+ zoneId = cmd.getNextArgRequired();
+ break;
+ }
+ default: {
+ throw new IllegalArgumentException("Unknown option: " + opt);
+ }
+ }
+ }
+ ManualTimeZoneSuggestion suggestion = new ManualTimeZoneSuggestion(zoneId);
+ suggestion.addDebugInfo("Command line injection");
+ return suggestion;
+ }
+
+ /** @hide */
+ public static void printCommandLineOpts(@NonNull PrintWriter pw) {
+ pw.println("Manual suggestion options:");
+ pw.println(" --zone_id <Olson ID>");
+ pw.println();
+ pw.println("See " + ManualTimeZoneSuggestion.class.getName() + " for more information");
+ }
}
diff --git a/core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.java b/core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.java
index 150c01d..430462b 100644
--- a/core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.java
+++ b/core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.java
@@ -21,7 +21,10 @@
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.ShellCommand;
+import android.text.TextUtils;
+import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -392,4 +395,96 @@
return new TelephonyTimeZoneSuggestion(this);
}
}
+
+ /** @hide */
+ public static TelephonyTimeZoneSuggestion parseCommandLineArg(@NonNull ShellCommand cmd)
+ throws IllegalArgumentException {
+ Integer slotIndex = null;
+ String zoneId = null;
+ Integer quality = null;
+ Integer matchType = null;
+ String opt;
+ while ((opt = cmd.getNextArg()) != null) {
+ switch (opt) {
+ case "--slot_index": {
+ slotIndex = Integer.parseInt(cmd.getNextArgRequired());
+ break;
+ }
+ case "--zone_id": {
+ zoneId = cmd.getNextArgRequired();
+ break;
+ }
+ case "--quality": {
+ quality = parseQualityCommandLineArg(cmd.getNextArgRequired());
+ break;
+ }
+ case "--match_type": {
+ matchType = parseMatchTypeCommandLineArg(cmd.getNextArgRequired());
+ break;
+ }
+ default: {
+ throw new IllegalArgumentException("Unknown option: " + opt);
+ }
+ }
+ }
+
+ if (slotIndex == null) {
+ throw new IllegalArgumentException("No slotIndex specified.");
+ }
+
+ Builder builder = new Builder(slotIndex);
+ if (!(TextUtils.isEmpty(zoneId) || "_".equals(zoneId))) {
+ builder.setZoneId(zoneId);
+ }
+ if (quality != null) {
+ builder.setQuality(quality);
+ }
+ if (matchType != null) {
+ builder.setMatchType(matchType);
+ }
+ builder.addDebugInfo("Command line injection");
+ return builder.build();
+ }
+
+ private static int parseQualityCommandLineArg(@NonNull String arg) {
+ switch (arg) {
+ case "single":
+ return QUALITY_SINGLE_ZONE;
+ case "multiple_same":
+ return QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
+ case "multiple_different":
+ return QUALITY_MULTIPLE_ZONES_WITH_DIFFERENT_OFFSETS;
+ default:
+ throw new IllegalArgumentException("Unrecognized quality: " + arg);
+ }
+ }
+
+ private static int parseMatchTypeCommandLineArg(@NonNull String arg) {
+ switch (arg) {
+ case "emulator":
+ return MATCH_TYPE_EMULATOR_ZONE_ID;
+ case "country_with_offset":
+ return MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET;
+ case "country":
+ return MATCH_TYPE_NETWORK_COUNTRY_ONLY;
+ case "test_network":
+ return MATCH_TYPE_TEST_NETWORK_OFFSET_ONLY;
+ default:
+ throw new IllegalArgumentException("Unrecognized match_type: " + arg);
+ }
+ }
+
+ /** @hide */
+ public static void printCommandLineOpts(@NonNull PrintWriter pw) {
+ pw.println("Telephony suggestion options:");
+ pw.println(" --slot_index <number>");
+ pw.println(" To withdraw a previous suggestion:");
+ pw.println(" [--zone_id \"_\"]");
+ pw.println(" To make a new suggestion:");
+ pw.println(" --zone_id <Olson ID>");
+ pw.println(" --quality <single|multiple_same|multiple_different>");
+ pw.println(" --match_type <emulator|country_with_offset|country|test_network>");
+ pw.println();
+ pw.println("See " + TelephonyTimeZoneSuggestion.class.getName() + " for more information");
+ }
}
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 5b98188..d6e7762 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -29,10 +29,10 @@
import android.net.DataUsageRequest;
import android.net.INetworkStatsService;
import android.net.NetworkIdentity;
+import android.net.NetworkStack;
import android.net.NetworkTemplate;
-import android.net.netstats.provider.AbstractNetworkStatsProvider;
-import android.net.netstats.provider.NetworkStatsProviderCallback;
-import android.net.netstats.provider.NetworkStatsProviderWrapper;
+import android.net.netstats.provider.INetworkStatsProviderCallback;
+import android.net.netstats.provider.NetworkStatsProvider;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
@@ -527,32 +527,53 @@
/**
* Registers a custom provider of {@link android.net.NetworkStats} to provide network statistics
- * to the system. To unregister, invoke {@link NetworkStatsProviderCallback#unregister()}.
+ * to the system. To unregister, invoke {@link #unregisterNetworkStatsProvider}.
* Note that no de-duplication of statistics between providers is performed, so each provider
- * must only report network traffic that is not being reported by any other provider.
+ * must only report network traffic that is not being reported by any other provider. Also note
+ * that the provider cannot be re-registered after unregistering.
*
* @param tag a human readable identifier of the custom network stats provider. This is only
* used for debugging.
- * @param provider the subclass of {@link AbstractNetworkStatsProvider} that needs to be
+ * @param provider the subclass of {@link NetworkStatsProvider} that needs to be
* registered to the system.
- * @return a {@link NetworkStatsProviderCallback}, which can be used to report events to the
- * system or unregister the provider.
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
- @NonNull public NetworkStatsProviderCallback registerNetworkStatsProvider(
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_STATS_PROVIDER,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
+ @NonNull public void registerNetworkStatsProvider(
@NonNull String tag,
- @NonNull AbstractNetworkStatsProvider provider) {
+ @NonNull NetworkStatsProvider provider) {
try {
- final NetworkStatsProviderWrapper wrapper = new NetworkStatsProviderWrapper(provider);
- return new NetworkStatsProviderCallback(
- mService.registerNetworkStatsProvider(tag, wrapper));
+ if (provider.getProviderCallbackBinder() != null) {
+ throw new IllegalArgumentException("provider is already registered");
+ }
+ final INetworkStatsProviderCallback cbBinder =
+ mService.registerNetworkStatsProvider(tag, provider.getProviderBinder());
+ provider.setProviderCallbackBinder(cbBinder);
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
- // Unreachable code, but compiler doesn't know about it.
- return null;
+ }
+
+ /**
+ * Unregisters an instance of {@link NetworkStatsProvider}.
+ *
+ * @param provider the subclass of {@link NetworkStatsProvider} that needs to be
+ * unregistered to the system.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_STATS_PROVIDER,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
+ @NonNull public void unregisterNetworkStatsProvider(@NonNull NetworkStatsProvider provider) {
+ try {
+ provider.getProviderCallbackBinderOrThrow().unregister();
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
}
private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index d4b5b1a..4bd7b05 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -257,11 +257,22 @@
/**
* Check if a given package was {@link #associate associated} with a device with given
- * mac address by given user.
+ * Wi-Fi MAC address for a given user.
*
- * @param packageName the package to check for
- * @param macAddress the mac address or BSSID of the device to check for
- * @param user the user to check for
+ * <p>This is a system API protected by the
+ * {@link andrioid.Manifest.permission#MANAGE_COMPANION_DEVICES} permission, that’s currently
+ * called by the Android Wi-Fi stack to determine whether user consent is required to connect
+ * to a Wi-Fi network. Devices that have been pre-registered as companion devices will not
+ * require user consent to connect.</p>
+ *
+ * <p>Note if the caller has the
+ * {@link android.Manifest.permission#COMPANION_APPROVE_WIFI_CONNECTIONS} permission, this
+ * method will return true by default.</p>
+ *
+ * @param packageName the name of the package that has the association with the companion device
+ * @param macAddress the Wi-Fi MAC address or BSSID of the companion device to check for
+ * @param user the user handle that currently hosts the package being queried for a companion
+ * device association
* @return whether a corresponding association record exists
*
* @hide
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 318ae11..6f46066 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3430,7 +3430,7 @@
TELEPHONY_SUBSCRIPTION_SERVICE,
CARRIER_CONFIG_SERVICE,
EUICC_SERVICE,
- MMS_SERVICE,
+ //@hide: MMS_SERVICE,
TELECOM_SERVICE,
CLIPBOARD_SERVICE,
INPUT_METHOD_SERVICE,
@@ -3984,8 +3984,6 @@
* @hide
* @see NetworkStackClient
*/
- @SystemApi
- @TestApi
public static final String NETWORK_STACK_SERVICE = "network_stack";
/**
@@ -4344,6 +4342,7 @@
*
* @see #getSystemService(String)
* @see android.telephony.MmsManager
+ * @hide
*/
public static final String MMS_SERVICE = "mms";
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 38c1890..95385ee 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3675,9 +3675,7 @@
* {@link android.Manifest.permission#MANAGE_USERS} to receive this broadcast.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @SystemApi
+ @UnsupportedAppUsage
public static final String ACTION_USER_SWITCHED =
"android.intent.action.USER_SWITCHED";
diff --git a/core/java/android/content/pm/IDataLoader.aidl b/core/java/android/content/pm/IDataLoader.aidl
index 6a2658d..5ec6341 100644
--- a/core/java/android/content/pm/IDataLoader.aidl
+++ b/core/java/android/content/pm/IDataLoader.aidl
@@ -29,9 +29,9 @@
void create(int id, in DataLoaderParamsParcel params,
in FileSystemControlParcel control,
IDataLoaderStatusListener listener);
- void start();
- void stop();
- void destroy();
+ void start(int id);
+ void stop(int id);
+ void destroy(int id);
- void prepareImage(in InstallationFileParcel[] addedFiles, in @utf8InCpp String[] removedFiles);
+ void prepareImage(int id, in InstallationFileParcel[] addedFiles, in @utf8InCpp String[] removedFiles);
}
diff --git a/core/java/android/content/pm/IDataLoaderStatusListener.aidl b/core/java/android/content/pm/IDataLoaderStatusListener.aidl
index 5011faa..9819b5d 100644
--- a/core/java/android/content/pm/IDataLoaderStatusListener.aidl
+++ b/core/java/android/content/pm/IDataLoaderStatusListener.aidl
@@ -31,9 +31,7 @@
const int DATA_LOADER_IMAGE_READY = 4;
const int DATA_LOADER_IMAGE_NOT_READY = 5;
- const int DATA_LOADER_SLOW_CONNECTION = 6;
- const int DATA_LOADER_NO_CONNECTION = 7;
- const int DATA_LOADER_CONNECTION_OK = 8;
+ const int DATA_LOADER_UNRECOVERABLE = 6;
/** Data loader status callback */
void onStatusChanged(in int dataLoaderId, in int status);
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 8a89840..27c9cfc 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -103,4 +103,7 @@
in UserHandle user);
void uncacheShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
in UserHandle user);
+
+ String getShortcutIconUri(String callingPackage, String packageName, String shortcutId,
+ int userId);
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 0311120..b52034f 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -680,8 +680,6 @@
String getWellbeingPackageName();
- String[] getTelephonyPackageNames();
-
String getAppPredictionServicePackageName();
String getSystemCaptionsServicePackageName();
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 4e4897f..e73fd03 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -51,6 +51,7 @@
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -67,8 +68,10 @@
import android.util.Log;
import android.util.Pair;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.function.pooled.PooledLambda;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -460,10 +463,7 @@
/**
* If non-null, return only the specified shortcuts by locus ID. When setting this field,
* a package name must also be set with {@link #setPackage}.
- *
- * @hide
*/
- @SystemApi
@NonNull
public ShortcutQuery setLocusIds(@Nullable List<LocusId> locusIds) {
mLocusIds = locusIds;
@@ -1201,6 +1201,35 @@
}
/**
+ * @hide internal/unit tests only
+ */
+ @VisibleForTesting
+ public ParcelFileDescriptor getUriShortcutIconFd(@NonNull ShortcutInfo shortcut) {
+ return getUriShortcutIconFd(shortcut.getPackage(), shortcut.getId(), shortcut.getUserId());
+ }
+
+ private ParcelFileDescriptor getUriShortcutIconFd(@NonNull String packageName,
+ @NonNull String shortcutId, int userId) {
+ String uri = null;
+ try {
+ uri = mService.getShortcutIconUri(mContext.getPackageName(), packageName, shortcutId,
+ userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+
+ if (uri == null) {
+ return null;
+ }
+ try {
+ return mContext.getContentResolver().openFileDescriptor(Uri.parse(uri), "r");
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "Icon file not found: " + uri);
+ return null;
+ }
+ }
+
+ /**
* Returns the icon for this shortcut, without any badging for the profile.
*
* <p>The calling launcher application must be allowed to access the shortcut information,
@@ -1220,26 +1249,10 @@
public Drawable getShortcutIconDrawable(@NonNull ShortcutInfo shortcut, int density) {
if (shortcut.hasIconFile()) {
final ParcelFileDescriptor pfd = getShortcutIconFd(shortcut);
- if (pfd == null) {
- return null;
- }
- try {
- final Bitmap bmp = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
- if (bmp != null) {
- BitmapDrawable dr = new BitmapDrawable(mContext.getResources(), bmp);
- if (shortcut.hasAdaptiveBitmap()) {
- return new AdaptiveIconDrawable(null, dr);
- } else {
- return dr;
- }
- }
- return null;
- } finally {
- try {
- pfd.close();
- } catch (IOException ignore) {
- }
- }
+ return loadDrawableFromFileDescriptor(pfd, shortcut.hasAdaptiveBitmap());
+ } else if (shortcut.hasIconUri()) {
+ final ParcelFileDescriptor pfd = getUriShortcutIconFd(shortcut);
+ return loadDrawableFromFileDescriptor(pfd, shortcut.hasAdaptiveBitmap());
} else if (shortcut.hasIconResource()) {
return loadDrawableResourceFromPackage(shortcut.getPackage(),
shortcut.getIconResourceId(), shortcut.getUserHandle(), density);
@@ -1263,6 +1276,29 @@
}
}
+ private Drawable loadDrawableFromFileDescriptor(ParcelFileDescriptor pfd, boolean adaptive) {
+ if (pfd == null) {
+ return null;
+ }
+ try {
+ final Bitmap bmp = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
+ if (bmp != null) {
+ BitmapDrawable dr = new BitmapDrawable(mContext.getResources(), bmp);
+ if (adaptive) {
+ return new AdaptiveIconDrawable(null, dr);
+ } else {
+ return dr;
+ }
+ }
+ return null;
+ } finally {
+ try {
+ pfd.close();
+ } catch (IOException ignore) {
+ }
+ }
+ }
+
private Drawable loadDrawableResourceFromPackage(String packageName, int resId,
UserHandle user, int density) {
try {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 05ff830..84eabdb 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -7796,18 +7796,6 @@
}
/**
- * @return the system defined telephony package names, or null if there's none.
- *
- * @hide
- */
- @Nullable
- @TestApi
- public String[] getTelephonyPackageNames() {
- throw new UnsupportedOperationException(
- "getTelephonyPackageNames not implemented in subclass");
- }
-
- /**
* @return the system defined content capture service package name, or null if there's none.
*
* @hide
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 3aa1a6d..c6c2882 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -239,17 +239,6 @@
/**
* Additional flag for {@link #protectionLevel}, corresponding
- * to the <code>telephony</code> value of
- * {@link android.R.attr#protectionLevel}.
- *
- * @hide
- */
- @SystemApi
- @TestApi
- public static final int PROTECTION_FLAG_TELEPHONY = 0x400000;
-
- /**
- * Additional flag for {@link #protectionLevel}, corresponding
* to the <code>companion</code> value of
* {@link android.R.attr#protectionLevel}.
*
@@ -291,7 +280,6 @@
PROTECTION_FLAG_CONFIGURATOR,
PROTECTION_FLAG_INCIDENT_REPORT_APPROVER,
PROTECTION_FLAG_APP_PREDICTOR,
- PROTECTION_FLAG_TELEPHONY,
PROTECTION_FLAG_COMPANION,
PROTECTION_FLAG_RETAIL_DEMO,
})
@@ -537,9 +525,6 @@
if ((level & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0) {
protLevel += "|appPredictor";
}
- if ((level & PermissionInfo.PROTECTION_FLAG_TELEPHONY) != 0) {
- protLevel += "|telephony";
- }
if ((level & PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) != 0) {
protLevel += "|retailDemo";
}
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index af87578..8d8776f 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -123,6 +123,9 @@
public static final int FLAG_CACHED = 1 << 14;
/** @hide */
+ public static final int FLAG_HAS_ICON_URI = 1 << 15;
+
+ /** @hide */
@IntDef(flag = true, prefix = { "FLAG_" }, value = {
FLAG_DYNAMIC,
FLAG_PINNED,
@@ -139,6 +142,7 @@
FLAG_SHADOW,
FLAG_LONG_LIVED,
FLAG_CACHED,
+ FLAG_HAS_ICON_URI,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ShortcutFlags {}
@@ -401,6 +405,9 @@
private String mIconResName;
// Internal use only.
+ private String mIconUri;
+
+ // Internal use only.
@Nullable
private String mBitmapPath;
@@ -554,6 +561,7 @@
if ((cloneFlags & CLONE_REMOVE_ICON) == 0) {
mIcon = source.mIcon;
mBitmapPath = source.mBitmapPath;
+ mIconUri = source.mIconUri;
}
mTitle = source.mTitle;
@@ -856,6 +864,7 @@
mIconResId = 0;
mIconResName = null;
mBitmapPath = null;
+ mIconUri = null;
}
if (source.mTitle != null) {
mTitle = source.mTitle;
@@ -916,6 +925,8 @@
case Icon.TYPE_RESOURCE:
case Icon.TYPE_BITMAP:
case Icon.TYPE_ADAPTIVE_BITMAP:
+ case Icon.TYPE_URI:
+ case Icon.TYPE_URI_ADAPTIVE_BITMAP:
break; // OK
default:
throw getInvalidIconException();
@@ -1792,6 +1803,15 @@
return hasFlags(FLAG_HAS_ICON_RES);
}
+ /**
+ * Return whether a shortcut's icon is provided via a URI.
+ *
+ * @hide internal/unit tests only
+ */
+ public boolean hasIconUri() {
+ return hasFlags(FLAG_HAS_ICON_URI);
+ }
+
/** @hide */
public boolean hasStringResources() {
return (mTitleResId != 0) || (mTextResId != 0) || (mDisabledMessageResId != 0);
@@ -1911,6 +1931,19 @@
return mIconResId;
}
+ /** @hide */
+ public void setIconUri(String iconUri) {
+ mIconUri = iconUri;
+ }
+
+ /**
+ * Get the Uri for the icon, valid only when {@link #hasIconUri()} } is true.
+ * @hide internal / tests only.
+ */
+ public String getIconUri() {
+ return mIconUri;
+ }
+
/**
* Bitmap path. Note this will be null even if {@link #hasIconFile()} is set when the save
* is pending. Use {@link #isIconPendingSave()} to check it.
@@ -2062,6 +2095,7 @@
mPersons = source.readParcelableArray(cl, Person.class);
mLocusId = source.readParcelable(cl);
+ mIconUri = source.readString();
}
@Override
@@ -2112,6 +2146,7 @@
dest.writeParcelableArray(mPersons, flags);
dest.writeParcelable(mLocusId, flags);
+ dest.writeString(mIconUri);
}
public static final @android.annotation.NonNull Creator<ShortcutInfo> CREATOR =
@@ -2203,6 +2238,12 @@
if (hasIconResource()) {
sb.append("Ic-r");
}
+ if (hasIconUri()) {
+ sb.append("Ic-u");
+ }
+ if (hasAdaptiveBitmap()) {
+ sb.append("Ic-a");
+ }
if (hasKeyFieldsOnly()) {
sb.append("Key");
}
@@ -2325,6 +2366,9 @@
sb.append(", bitmapPath=");
sb.append(mBitmapPath);
+
+ sb.append(", iconUri=");
+ sb.append(mIconUri);
}
if (mLocusId != null) {
@@ -2343,8 +2387,8 @@
CharSequence disabledMessage, int disabledMessageResId, String disabledMessageResName,
Set<String> categories, Intent[] intentsWithExtras, int rank, PersistableBundle extras,
long lastChangedTimestamp,
- int flags, int iconResId, String iconResName, String bitmapPath, int disabledReason,
- Person[] persons, LocusId locusId) {
+ int flags, int iconResId, String iconResName, String bitmapPath, String iconUri,
+ int disabledReason, Person[] persons, LocusId locusId) {
mUserId = userId;
mId = id;
mPackageName = packageName;
@@ -2369,6 +2413,7 @@
mIconResId = iconResId;
mIconResName = iconResName;
mBitmapPath = bitmapPath;
+ mIconUri = iconUri;
mDisabledReason = disabledReason;
mPersons = persons;
mLocusId = locusId;
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index a50ce92..435c70a 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -103,4 +103,10 @@
*/
public abstract List<ShortcutManager.ShareShortcutInfo> getShareTargets(
@NonNull String callingPackage, @NonNull IntentFilter intentFilter, int userId);
+
+ /**
+ * Returns the icon Uri of the shortcut, and grants Uri read permission to the caller.
+ */
+ public abstract String getShortcutIconUri(int launcherUserId, @NonNull String launcherPackage,
+ @NonNull String packageName, @NonNull String shortcutId, int userId);
}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index e41ed85..6f8acb6 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -1820,8 +1820,8 @@
.setUseEmbeddedDex(bool(false, R.styleable.AndroidManifestApplication_useEmbeddedDex, sa))
.setUsesNonSdkApi(bool(false, R.styleable.AndroidManifestApplication_usesNonSdkApi, sa))
.setVmSafeMode(bool(false, R.styleable.AndroidManifestApplication_vmSafeMode, sa))
- .setDontAutoRevokePermissions(bool(false, R.styleable.AndroidManifestApplication_requestDontAutoRevokePermissions, sa))
- .setAllowDontAutoRevokePermissions(bool(false, R.styleable.AndroidManifestApplication_allowDontAutoRevokePermissions, sa))
+ .setDontAutoRevokePermissions(bool(false, R.styleable.AndroidManifestApplication_requestAutoRevokePermissionsExemption, sa))
+ .setAllowDontAutoRevokePermissions(bool(false, R.styleable.AndroidManifestApplication_allowAutoRevokePermissionsExemption, sa))
// targetSdkVersion gated
.setAllowAudioPlaybackCapture(bool(targetSdk >= Build.VERSION_CODES.Q, R.styleable.AndroidManifestApplication_allowAudioPlaybackCapture, sa))
.setBaseHardwareAccelerated(bool(targetSdk >= Build.VERSION_CODES.ICE_CREAM_SANDWICH, R.styleable.AndroidManifestApplication_hardwareAccelerated, sa))
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 5fbf0da..9906331 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -657,7 +657,9 @@
public int accuracy;
/**
- * The time in nanosecond at which the event happened
+ * The time in nanoseconds at which the event happened. For a given sensor,
+ * each new sensor event should be monotonically increasing using the same
+ * time base as {@link android.os.SystemClock#elapsedRealtimeNanos()}.
*/
public long timestamp;
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 7e72b73d..737fe60 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -2860,6 +2860,29 @@
new Key<android.hardware.camera2.params.MandatoryStreamCombination[]>("android.scaler.mandatoryStreamCombinations", android.hardware.camera2.params.MandatoryStreamCombination[].class);
/**
+ * <p>An array of mandatory concurrent stream combinations.
+ * This is an app-readable conversion of the concurrent mandatory stream combination
+ * {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
+ * <p>The array of
+ * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
+ * generated according to the documented
+ * {@link android.hardware.camera2.CameraDevice#createCaptureSession guideline} for each
+ * device which has its Id present in the set returned by
+ * {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds }.
+ * Clients can use the array as a quick reference to find an appropriate camera stream
+ * combination.
+ * The mandatory stream combination array will be {@code null} in case the device is not a
+ * part of at least one set of combinations returned by
+ * {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds }.</p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ */
+ @PublicKey
+ @NonNull
+ @SyntheticKey
+ public static final Key<android.hardware.camera2.params.MandatoryStreamCombination[]> SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS =
+ new Key<android.hardware.camera2.params.MandatoryStreamCombination[]>("android.scaler.mandatoryConcurrentStreamCombinations", android.hardware.camera2.params.MandatoryStreamCombination[].class);
+
+ /**
* <p>List of rotate-and-crop modes for {@link CaptureRequest#SCALER_ROTATE_AND_CROP android.scaler.rotateAndCrop} that are supported by this camera device.</p>
* <p>This entry lists the valid modes for {@link CaptureRequest#SCALER_ROTATE_AND_CROP android.scaler.rotateAndCrop} for this camera device.</p>
* <p>Starting with API level 30, all devices will list at least <code>ROTATE_AND_CROP_NONE</code>.
@@ -2875,28 +2898,7 @@
@NonNull
public static final Key<int[]> SCALER_AVAILABLE_ROTATE_AND_CROP_MODES =
new Key<int[]>("android.scaler.availableRotateAndCropModes", int[].class);
- /**
- * <p>An array of mandatory concurrent stream combinations.
- * This is an app-readable conversion of the concurrent mandatory stream combination
- * {@link android.hardware.camera2.CameraDevice#createCaptureSession tables}.</p>
- * <p>The array of
- * {@link android.hardware.camera2.params.MandatoryStreamCombination combinations} is
- * generated according to the documented
- * {@link android.hardware.camera2.CameraDevice#createCaptureSession guideline} for each device
- * which has its Id present in the set returned by
- * {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds}.
- * Clients can use the array as a quick reference to find an appropriate camera stream
- * combination.
- * The mandatory stream combination array will be {@code null} in case the device is not a part
- * of at least one set of combinations returned by
- * {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds}.</p>
- * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
- */
- @PublicKey
- @NonNull
- @SyntheticKey
- public static final Key<android.hardware.camera2.params.MandatoryStreamCombination[]> SCALER_MANDATORY_CONCURRENT_STREAM_COMBINATIONS =
- new Key<android.hardware.camera2.params.MandatoryStreamCombination[]>("android.scaler.mandatoryConcurrentStreamCombinations", android.hardware.camera2.params.MandatoryStreamCombination[].class);
+
/**
* <p>The area of the image sensor which corresponds to active pixels after any geometric
* distortion correction has been applied.</p>
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 8f3cb93..45d6fed 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1066,8 +1066,9 @@
* <li>One Jpeg ImageReader, any resolution: the camera device is
* allowed to slow down JPEG output speed by 50% if there is any ongoing offline
* session.</li>
- * <li>One ImageWriter surface of private format, any resolution if the device supports
- * PRIVATE_REPROCESSING capability</li>
+ * <li>If the device supports PRIVATE_REPROCESSING, one pair of ImageWriter/ImageReader
+ * surfaces of private format, with the same resolution that is larger or equal to
+ * the JPEG ImageReader resolution above.</li>
* </ol>
* </li>
* <li>Alternatively, the active camera session above can be replaced by an legacy
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 1b6c1ee..7e4d68d 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -20,6 +20,7 @@
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.WindowInsets.Type.navigationBars;
+import static android.view.WindowInsets.Type.statusBars;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -71,6 +72,7 @@
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowInsets;
+import android.view.WindowInsets.Side;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.view.autofill.AutofillId;
@@ -1246,7 +1248,8 @@
Context.LAYOUT_INFLATER_SERVICE);
mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
WindowManager.LayoutParams.TYPE_INPUT_METHOD, Gravity.BOTTOM, false);
- mWindow.getWindow().getAttributes().setFitInsetsTypes(WindowInsets.Type.statusBars());
+ mWindow.getWindow().getAttributes().setFitInsetsTypes(statusBars() | navigationBars());
+ mWindow.getWindow().getAttributes().setFitInsetsSides(Side.all() & ~Side.BOTTOM);
// IME layout should always be inset by navigation bar, no matter its current visibility,
// unless automotive requests it, since automotive may hide the navigation bar.
diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java
index 1710ccb..6f0a4f9 100644
--- a/core/java/android/net/ConnectivityDiagnosticsManager.java
+++ b/core/java/android/net/ConnectivityDiagnosticsManager.java
@@ -136,7 +136,7 @@
* {@link #NETWORK_VALIDATION_RESULT_PARTIALLY_VALID},
* {@link #NETWORK_VALIDATION_RESULT_SKIPPED}.
*
- * @see android.net.NetworkCapabilities#CAPABILITY_VALIDATED
+ * @see android.net.NetworkCapabilities#NET_CAPABILITY_VALIDATED
*/
@NetworkValidationResult
public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult";
@@ -233,8 +233,8 @@
* Constructor for ConnectivityReport.
*
* <p>Apps should obtain instances through {@link
- * ConnectivityDiagnosticsCallback#onConnectivityReport} instead of instantiating their own
- * instances (unless for testing purposes).
+ * ConnectivityDiagnosticsCallback#onConnectivityReportAvailable} instead of instantiating
+ * their own instances (unless for testing purposes).
*
* @param network The Network for which this ConnectivityReport applies
* @param reportTimestamp The timestamp for the report
@@ -622,10 +622,10 @@
/** @hide */
@VisibleForTesting
- public void onConnectivityReport(@NonNull ConnectivityReport report) {
+ public void onConnectivityReportAvailable(@NonNull ConnectivityReport report) {
Binder.withCleanCallingIdentity(() -> {
mExecutor.execute(() -> {
- mCb.onConnectivityReport(report);
+ mCb.onConnectivityReportAvailable(report);
});
});
}
@@ -666,7 +666,7 @@
*
* @param report The ConnectivityReport containing information about a connectivity check
*/
- public void onConnectivityReport(@NonNull ConnectivityReport report) {}
+ public void onConnectivityReportAvailable(@NonNull ConnectivityReport report) {}
/**
* Called when the platform suspects a data stall on some Network.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 81735ac..2418014 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -145,16 +145,6 @@
public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
/**
- * A temporary hack until SUPL system can get off the legacy APIS.
- * They do too many network requests and the long list of apps listening
- * and waking due to the CONNECTIVITY_ACTION broadcast makes it expensive.
- * Use this broadcast intent instead for SUPL requests.
- * @hide
- */
- public static final String CONNECTIVITY_ACTION_SUPL =
- "android.net.conn.CONNECTIVITY_CHANGE_SUPL";
-
- /**
* The device has connected to a network that has presented a captive
* portal, which is blocking Internet connectivity. The user was presented
* with a notification that network sign in is required,
@@ -1517,84 +1507,6 @@
return null;
}
- /**
- * Guess what the network request was trying to say so that the resulting
- * network is accessible via the legacy (deprecated) API such as
- * requestRouteToHost.
- *
- * This means we should try to be fairly precise about transport and
- * capability but ignore things such as networkSpecifier.
- * If the request has more than one transport or capability it doesn't
- * match the old legacy requests (they selected only single transport/capability)
- * so this function cannot map the request to a single legacy type and
- * the resulting network will not be available to the legacy APIs.
- *
- * This code is only called from the requestNetwork API (L and above).
- *
- * Setting a legacy type causes CONNECTIVITY_ACTION broadcasts, which are expensive
- * because they wake up lots of apps - see http://b/23350688 . So we currently only
- * do this for SUPL requests, which are the only ones that we know need it. If
- * omitting these broadcasts causes unacceptable app breakage, then for backwards
- * compatibility we can send them:
- *
- * if (targetSdkVersion < Build.VERSION_CODES.M) && // legacy API unsupported >= M
- * targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP)) // requestNetwork not present < L
- *
- * TODO - This should be removed when the legacy APIs are removed.
- */
- private int inferLegacyTypeForNetworkCapabilities(NetworkCapabilities netCap) {
- if (netCap == null) {
- return TYPE_NONE;
- }
-
- if (!netCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
- return TYPE_NONE;
- }
-
- // Do this only for SUPL, until GnssLocationProvider is fixed. http://b/25876485 .
- if (!netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
- // NOTE: if this causes app breakage, we should not just comment out this early return;
- // instead, we should make this early return conditional on the requesting app's target
- // SDK version, as described in the comment above.
- return TYPE_NONE;
- }
-
- String type = null;
- int result = TYPE_NONE;
-
- if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
- type = "enableCBS";
- result = TYPE_MOBILE_CBS;
- } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
- type = "enableIMS";
- result = TYPE_MOBILE_IMS;
- } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) {
- type = "enableFOTA";
- result = TYPE_MOBILE_FOTA;
- } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) {
- type = "enableDUN";
- result = TYPE_MOBILE_DUN;
- } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
- type = "enableSUPL";
- result = TYPE_MOBILE_SUPL;
- // back out this hack for mms as they no longer need this and it's causing
- // device slowdowns - b/23350688 (note, supl still needs this)
- //} else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
- // type = "enableMMS";
- // result = TYPE_MOBILE_MMS;
- } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
- type = "enableHIPRI";
- result = TYPE_MOBILE_HIPRI;
- }
- if (type != null) {
- NetworkCapabilities testCap = networkCapabilitiesForFeature(TYPE_MOBILE, type);
- if (testCap.equalsNetCapabilities(netCap) && testCap.equalsTransportTypes(netCap)) {
- return result;
- }
- }
- return TYPE_NONE;
- }
-
private int legacyTypeForNetworkCapabilities(NetworkCapabilities netCap) {
if (netCap == null) return TYPE_NONE;
if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
@@ -2575,13 +2487,13 @@
}
@Override
- public void onTetheringFailed(final int resultCode) {
+ public void onTetheringFailed(final int error) {
callback.onTetheringFailed();
}
};
final TetheringRequest request = new TetheringRequest.Builder(type)
- .setSilentProvisioning(!showProvisioningUi).build();
+ .setShouldShowEntitlementUi(showProvisioningUi).build();
mTetheringManager.startTethering(request, executor, tetheringCallback);
}
@@ -2801,11 +2713,12 @@
public static final int TETHER_ERROR_UNAVAIL_IFACE =
TetheringManager.TETHER_ERROR_UNAVAIL_IFACE;
/**
- * @deprecated Use {@link TetheringManager#TETHER_ERROR_MASTER_ERROR}.
+ * @deprecated Use {@link TetheringManager#TETHER_ERROR_INTERNAL_ERROR}.
* {@hide}
*/
@Deprecated
- public static final int TETHER_ERROR_MASTER_ERROR = TetheringManager.TETHER_ERROR_MASTER_ERROR;
+ public static final int TETHER_ERROR_MASTER_ERROR =
+ TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
/**
* @deprecated Use {@link TetheringManager#TETHER_ERROR_TETHER_IFACE_ERROR}.
* {@hide}
@@ -2821,19 +2734,19 @@
public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR =
TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
/**
- * @deprecated Use {@link TetheringManager#TETHER_ERROR_ENABLE_NAT_ERROR}.
+ * @deprecated Use {@link TetheringManager#TETHER_ERROR_ENABLE_FORWARDING_ERROR}.
* {@hide}
*/
@Deprecated
public static final int TETHER_ERROR_ENABLE_NAT_ERROR =
- TetheringManager.TETHER_ERROR_ENABLE_NAT_ERROR;
+ TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;
/**
- * @deprecated Use {@link TetheringManager#TETHER_ERROR_DISABLE_NAT_ERROR}.
+ * @deprecated Use {@link TetheringManager#TETHER_ERROR_DISABLE_FORWARDING_ERROR}.
* {@hide}
*/
@Deprecated
public static final int TETHER_ERROR_DISABLE_NAT_ERROR =
- TetheringManager.TETHER_ERROR_DISABLE_NAT_ERROR;
+ TetheringManager.TETHER_ERROR_DISABLE_FORWARDING_ERROR;
/**
* @deprecated Use {@link TetheringManager#TETHER_ERROR_IFACE_CFG_ERROR}.
* {@hide}
@@ -2842,13 +2755,13 @@
public static final int TETHER_ERROR_IFACE_CFG_ERROR =
TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
/**
- * @deprecated Use {@link TetheringManager#TETHER_ERROR_PROVISION_FAILED}.
+ * @deprecated Use {@link TetheringManager#TETHER_ERROR_PROVISIONING_FAILED}.
* {@hide}
*/
@SystemApi
@Deprecated
public static final int TETHER_ERROR_PROVISION_FAILED =
- TetheringManager.TETHER_ERROR_PROVISION_FAILED;
+ TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
/**
* @deprecated Use {@link TetheringManager#TETHER_ERROR_DHCPSERVER_ERROR}.
* {@hide}
@@ -2880,7 +2793,14 @@
@UnsupportedAppUsage
@Deprecated
public int getLastTetherError(String iface) {
- return mTetheringManager.getLastTetherError(iface);
+ int error = mTetheringManager.getLastTetherError(iface);
+ if (error == TetheringManager.TETHER_ERROR_UNKNOWN_TYPE) {
+ // TETHER_ERROR_UNKNOWN_TYPE was introduced with TetheringManager and has never been
+ // returned by ConnectivityManager. Convert it to the legacy TETHER_ERROR_UNKNOWN_IFACE
+ // instead.
+ error = TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
+ }
+ return error;
}
/** @hide */
@@ -3893,9 +3813,8 @@
*/
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback, @NonNull Handler handler) {
- int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
CallbackHandler cbHandler = new CallbackHandler(handler);
- requestNetwork(request, networkCallback, 0, legacyType, cbHandler);
+ requestNetwork(request, networkCallback, 0, TYPE_NONE, cbHandler);
}
/**
@@ -3928,8 +3847,7 @@
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback, int timeoutMs) {
checkTimeout(timeoutMs);
- int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
- requestNetwork(request, networkCallback, timeoutMs, legacyType, getDefaultHandler());
+ requestNetwork(request, networkCallback, timeoutMs, TYPE_NONE, getDefaultHandler());
}
/**
@@ -3954,9 +3872,8 @@
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback, @NonNull Handler handler, int timeoutMs) {
checkTimeout(timeoutMs);
- int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities);
CallbackHandler cbHandler = new CallbackHandler(handler);
- requestNetwork(request, networkCallback, timeoutMs, legacyType, cbHandler);
+ requestNetwork(request, networkCallback, timeoutMs, TYPE_NONE, cbHandler);
}
/**
diff --git a/core/java/android/net/IConnectivityDiagnosticsCallback.aidl b/core/java/android/net/IConnectivityDiagnosticsCallback.aidl
index 3a161bf..82b64a9 100644
--- a/core/java/android/net/IConnectivityDiagnosticsCallback.aidl
+++ b/core/java/android/net/IConnectivityDiagnosticsCallback.aidl
@@ -22,7 +22,7 @@
/** @hide */
oneway interface IConnectivityDiagnosticsCallback {
- void onConnectivityReport(in ConnectivityDiagnosticsManager.ConnectivityReport report);
+ void onConnectivityReportAvailable(in ConnectivityDiagnosticsManager.ConnectivityReport report);
void onDataStallSuspected(in ConnectivityDiagnosticsManager.DataStallReport report);
void onNetworkConnectivityReported(in Network n, boolean hasConnectivity);
}
\ No newline at end of file
diff --git a/core/java/android/net/ITestNetworkManager.aidl b/core/java/android/net/ITestNetworkManager.aidl
index d586038..2a863ad 100644
--- a/core/java/android/net/ITestNetworkManager.aidl
+++ b/core/java/android/net/ITestNetworkManager.aidl
@@ -33,7 +33,7 @@
TestNetworkInterface createTapInterface();
void setupTestNetwork(in String iface, in LinkProperties lp, in boolean isMetered,
- in IBinder binder);
+ in int[] administratorUids, in IBinder binder);
void teardownTestNetwork(int netId);
}
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 732ceb5..2c356e4 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -167,7 +167,19 @@
this(source, false /* parcelSensitiveFields */);
}
- private LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) {
+ /**
+ * Create a copy of a {@link LinkProperties} that may preserve fields that were set
+ * based on the permissions of the process that originally received it.
+ *
+ * <p>By default {@link LinkProperties} does not preserve such fields during parceling, as
+ * they should not be shared outside of the process that receives them without appropriate
+ * checks.
+ * @param parcelSensitiveFields Whether the sensitive fields should be kept when parceling
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) {
mParcelSensitiveFields = parcelSensitiveFields;
if (source == null) return;
mIfaceName = source.mIfaceName;
@@ -674,17 +686,29 @@
route.getDestination(),
route.getGateway(),
mIfaceName,
- route.getType());
+ route.getType(),
+ route.getMtu());
+ }
+
+ private int findRouteIndexByDestination(RouteInfo route) {
+ for (int i = 0; i < mRoutes.size(); i++) {
+ if (mRoutes.get(i).isSameDestinationAs(route)) {
+ return i;
+ }
+ }
+ return -1;
}
/**
- * Adds a {@link RouteInfo} to this {@code LinkProperties}, if not present. If the
- * {@link RouteInfo} had an interface name set and that differs from the interface set for this
- * {@code LinkProperties} an {@link IllegalArgumentException} will be thrown. The proper
+ * Adds a {@link RouteInfo} to this {@code LinkProperties}, if a {@link RouteInfo}
+ * with the same destination exists with different properties (e.g., different MTU),
+ * it will be updated. If the {@link RouteInfo} had an interface name set and
+ * that differs from the interface set for this {@code LinkProperties} an
+ * {@link IllegalArgumentException} will be thrown. The proper
* course is to add either un-named or properly named {@link RouteInfo}.
*
* @param route A {@link RouteInfo} to add to this object.
- * @return {@code false} if the route was already present, {@code true} if it was added.
+ * @return {@code true} was added or updated, false otherwise.
*/
public boolean addRoute(@NonNull RouteInfo route) {
String routeIface = route.getInterface();
@@ -694,11 +718,20 @@
+ " vs. " + mIfaceName);
}
route = routeWithInterface(route);
- if (!mRoutes.contains(route)) {
+
+ int i = findRouteIndexByDestination(route);
+ if (i == -1) {
+ // Route was not present. Add it.
mRoutes.add(route);
return true;
+ } else if (mRoutes.get(i).equals(route)) {
+ // Route was present and has same properties. Do nothing.
+ return false;
+ } else {
+ // Route was present and has different properties. Update it.
+ mRoutes.set(i, route);
+ return true;
}
- return false;
}
/**
@@ -706,6 +739,7 @@
* specify an interface and the interface must match the interface of this
* {@code LinkProperties}, or it will not be removed.
*
+ * @param route A {@link RouteInfo} specifying the route to remove.
* @return {@code true} if the route was removed, {@code false} if it was not present.
*
* @hide
@@ -1561,22 +1595,6 @@
}
/**
- * Create a copy of this {@link LinkProperties} that will preserve fields that were set
- * based on the permissions of the process that received this {@link LinkProperties}.
- *
- * <p>By default {@link LinkProperties} does not preserve such fields during parceling, as
- * they should not be shared outside of the process that receives them without appropriate
- * checks.
- * @hide
- */
- @SystemApi
- @TestApi
- @NonNull
- public LinkProperties makeSensitiveFieldsParcelingCopy() {
- return new LinkProperties(this, true /* parcelSensitiveFields */);
- }
-
- /**
* Compares this {@code LinkProperties} instance against the target
* LinkProperties in {@code obj}. Two LinkPropertieses are equal if
* all their fields are equal in values.
diff --git a/core/java/android/net/NattKeepalivePacketData.java b/core/java/android/net/NattKeepalivePacketData.java
index bd39c13..29da495 100644
--- a/core/java/android/net/NattKeepalivePacketData.java
+++ b/core/java/android/net/NattKeepalivePacketData.java
@@ -20,6 +20,7 @@
import static android.net.InvalidPacketException.ERROR_INVALID_PORT;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.net.util.IpUtils;
import android.os.Parcel;
@@ -30,6 +31,7 @@
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.util.Objects;
/** @hide */
@SystemApi
@@ -121,4 +123,19 @@
return new NattKeepalivePacketData[size];
}
};
+
+ @Override
+ public boolean equals(@Nullable final Object o) {
+ if (!(o instanceof NattKeepalivePacketData)) return false;
+ final NattKeepalivePacketData other = (NattKeepalivePacketData) o;
+ return this.srcAddress.equals(other.srcAddress)
+ && this.dstAddress.equals(other.dstAddress)
+ && this.srcPort == other.srcPort
+ && this.dstPort == other.dstPort;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(srcAddress, dstAddress, srcPort, dstPort);
+ }
}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 116e343..7d8df6a 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -37,9 +37,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import java.util.Arrays;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
@@ -96,7 +94,7 @@
mTransportInfo = null;
mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
mUids = null;
- mAdministratorUids.clear();
+ mAdministratorUids = new int[0];
mOwnerUid = Process.INVALID_UID;
mSSID = null;
mPrivateDnsBroken = false;
@@ -884,10 +882,10 @@
* empty unless the destination is 1) the System Server, or 2) Telephony. In either case, the
* receiving entity must have the ACCESS_FINE_LOCATION permission and target R+.
*/
- private final List<Integer> mAdministratorUids = new ArrayList<>();
+ private int[] mAdministratorUids = new int[0];
/**
- * Sets the list of UIDs that are administrators of this network.
+ * Sets the int[] of UIDs that are administrators of this network.
*
* <p>UIDs included in administratorUids gain administrator privileges over this Network.
* Examples of UIDs that should be included in administratorUids are:
@@ -907,23 +905,21 @@
*/
@NonNull
@SystemApi
- public NetworkCapabilities setAdministratorUids(
- @NonNull final List<Integer> administratorUids) {
- mAdministratorUids.clear();
- mAdministratorUids.addAll(administratorUids);
+ public NetworkCapabilities setAdministratorUids(@NonNull final int[] administratorUids) {
+ mAdministratorUids = Arrays.copyOf(administratorUids, administratorUids.length);
return this;
}
/**
- * Retrieves the list of UIDs that are administrators of this Network.
+ * Retrieves the UIDs that are administrators of this Network.
*
- * @return the List of UIDs that are administrators of this Network
+ * @return the int[] of UIDs that are administrators of this Network
* @hide
*/
@NonNull
@SystemApi
- public List<Integer> getAdministratorUids() {
- return Collections.unmodifiableList(mAdministratorUids);
+ public int[] getAdministratorUids() {
+ return Arrays.copyOf(mAdministratorUids, mAdministratorUids.length);
}
/**
@@ -1584,7 +1580,7 @@
dest.writeArraySet(mUids);
dest.writeString(mSSID);
dest.writeBoolean(mPrivateDnsBroken);
- dest.writeList(mAdministratorUids);
+ dest.writeIntArray(mAdministratorUids);
dest.writeInt(mOwnerUid);
dest.writeInt(mRequestorUid);
dest.writeString(mRequestorPackageName);
@@ -1608,7 +1604,7 @@
null /* ClassLoader, null for default */);
netCap.mSSID = in.readString();
netCap.mPrivateDnsBroken = in.readBoolean();
- netCap.setAdministratorUids(in.readArrayList(null));
+ netCap.setAdministratorUids(in.createIntArray());
netCap.mOwnerUid = in.readInt();
netCap.mRequestorUid = in.readInt();
netCap.mRequestorPackageName = in.readString();
@@ -1665,8 +1661,8 @@
sb.append(" OwnerUid: ").append(mOwnerUid);
}
- if (!mAdministratorUids.isEmpty()) {
- sb.append(" AdministratorUids: ").append(mAdministratorUids);
+ if (mAdministratorUids.length == 0) {
+ sb.append(" AdministratorUids: ").append(Arrays.toString(mAdministratorUids));
}
if (null != mSSID) {
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index c1198aa..0948a4da 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -25,6 +25,7 @@
import android.net.wifi.WifiManager;
import android.os.Build;
import android.service.NetworkIdentityProto;
+import android.telephony.Annotation.NetworkType;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -39,16 +40,6 @@
public class NetworkIdentity implements Comparable<NetworkIdentity> {
private static final String TAG = "NetworkIdentity";
- /**
- * When enabled, combine all {@link #mSubType} together under
- * {@link #SUBTYPE_COMBINED}.
- *
- * @deprecated we no longer offer to collect statistics on a per-subtype
- * basis; this is always disabled.
- */
- @Deprecated
- public static final boolean COMBINE_SUBTYPE_ENABLED = true;
-
public static final int SUBTYPE_COMBINED = -1;
final int mType;
@@ -63,7 +54,7 @@
int type, int subType, String subscriberId, String networkId, boolean roaming,
boolean metered, boolean defaultNetwork) {
mType = type;
- mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
+ mSubType = subType;
mSubscriberId = subscriberId;
mNetworkId = networkId;
mRoaming = roaming;
@@ -95,7 +86,7 @@
final StringBuilder builder = new StringBuilder("{");
builder.append("type=").append(getNetworkTypeName(mType));
builder.append(", subType=");
- if (COMBINE_SUBTYPE_ENABLED) {
+ if (mSubType == SUBTYPE_COMBINED) {
builder.append("COMBINED");
} else {
builder.append(mSubType);
@@ -187,13 +178,14 @@
}
/**
- * Build a {@link NetworkIdentity} from the given {@link NetworkState},
- * assuming that any mobile networks are using the current IMSI.
+ * Build a {@link NetworkIdentity} from the given {@link NetworkState} and {@code subType},
+ * assuming that any mobile networks are using the current IMSI. The subType if applicable,
+ * should be set as one of the TelephonyManager.NETWORK_TYPE_* constants, or
+ * {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not.
*/
public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state,
- boolean defaultNetwork) {
+ boolean defaultNetwork, @NetworkType int subType) {
final int type = state.networkInfo.getType();
- final int subType = state.networkInfo.getSubtype();
String subscriberId = null;
String networkId = null;
diff --git a/core/java/android/net/NetworkStack.java b/core/java/android/net/NetworkStack.java
index a46c410..a6d52d1 100644
--- a/core/java/android/net/NetworkStack.java
+++ b/core/java/android/net/NetworkStack.java
@@ -19,15 +19,17 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.content.Context;
+import android.os.IBinder;
+import android.os.ServiceManager;
import java.util.ArrayList;
import java.util.Arrays;
/**
- *
- * Constants for client code communicating with the network stack service.
+ * Constants and utilities for client code communicating with the network stack service.
* @hide
*/
@SystemApi
@@ -43,6 +45,17 @@
public static final String PERMISSION_MAINLINE_NETWORK_STACK =
"android.permission.MAINLINE_NETWORK_STACK";
+ /**
+ * Get an {@link IBinder} representing the NetworkStack stable AIDL Interface, if registered.
+ * @hide
+ */
+ @Nullable
+ @SystemApi
+ @TestApi
+ public static IBinder getService() {
+ return ServiceManager.getService(Context.NETWORK_STACK_SERVICE);
+ }
+
private NetworkStack() {}
/**
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 2f536ff..9c1fb41 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -21,7 +21,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
@@ -58,9 +57,12 @@
public final class NetworkStats implements Parcelable {
private static final String TAG = "NetworkStats";
- /** {@link #iface} value when interface details unavailable. */
- @SuppressLint("CompileTimeConstant")
+ /**
+ * {@link #iface} value when interface details unavailable.
+ * @hide
+ */
@Nullable public static final String IFACE_ALL = null;
+
/**
* Virtual network interface for video telephony. This is for VT data usage counting
* purpose.
@@ -248,7 +250,13 @@
@UnsupportedAppUsage
private long[] operations;
- /** @hide */
+ /**
+ * Basic element of network statistics. Contains the number of packets and number of bytes
+ * transferred on both directions in a given set of conditions. See
+ * {@link Entry#Entry(String, int, int, int, int, int, int, long, long, long, long, long)}.
+ *
+ * @hide
+ */
@SystemApi
public static class Entry {
/** @hide */
@@ -319,6 +327,35 @@
rxBytes, rxPackets, txBytes, txPackets, operations);
}
+ /**
+ * Construct a {@link Entry} object by giving statistics of packet and byte transferred on
+ * both direction, and associated with a set of given conditions.
+ *
+ * @param iface interface name of this {@link Entry}. Or null if not specified.
+ * @param uid uid of this {@link Entry}. {@link #UID_TETHERING} if this {@link Entry} is
+ * for tethering. Or {@link #UID_ALL} if this {@link NetworkStats} is only
+ * counting iface stats.
+ * @param set usage state of this {@link Entry}. Should be one of the following
+ * values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}.
+ * @param tag tag of this {@link Entry}.
+ * @param metered metered state of this {@link Entry}. Should be one of the following
+ * values: {link #METERED_YES}, {link #METERED_NO}.
+ * @param roaming roaming state of this {@link Entry}. Should be one of the following
+ * values: {link #ROAMING_YES}, {link #ROAMING_NO}.
+ * @param defaultNetwork default network status of this {@link Entry}. Should be one
+ * of the following values: {link #DEFAULT_NETWORK_YES},
+ * {link #DEFAULT_NETWORK_NO}.
+ * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should
+ * represent the contents of IP packets, including IP headers.
+ * @param rxPackets Number of packets received for this {@link Entry}. Statistics should
+ * represent the contents of IP packets, including IP headers.
+ * @param txBytes Number of bytes transmitted for this {@link Entry}. Statistics should
+ * represent the contents of IP packets, including IP headers.
+ * @param txPackets Number of bytes transmitted for this {@link Entry}. Statistics should
+ * represent the contents of IP packets, including IP headers.
+ * @param operations count of network operations performed for this {@link Entry}. This can
+ * be used to derive bytes-per-operation.
+ */
public Entry(@Nullable String iface, int uid, @State int set, int tag,
@Meteredness int metered, @Roaming int roaming, @DefaultNetwork int defaultNetwork,
long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
@@ -466,7 +503,7 @@
NetworkStats.Entry entry = null;
for (int i = 0; i < size; i++) {
entry = getValues(i, entry);
- clone.addEntry(entry);
+ clone.insertEntry(entry);
}
return clone;
}
@@ -493,26 +530,26 @@
/** @hide */
@VisibleForTesting
- public NetworkStats addIfaceValues(
+ public NetworkStats insertEntry(
String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
- return addEntry(
+ return insertEntry(
iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
}
/** @hide */
@VisibleForTesting
- public NetworkStats addEntry(String iface, int uid, int set, int tag, long rxBytes,
+ public NetworkStats insertEntry(String iface, int uid, int set, int tag, long rxBytes,
long rxPackets, long txBytes, long txPackets, long operations) {
- return addEntry(new Entry(
+ return insertEntry(new Entry(
iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
}
/** @hide */
@VisibleForTesting
- public NetworkStats addEntry(String iface, int uid, int set, int tag, int metered, int roaming,
- int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets,
- long operations) {
- return addEntry(new Entry(
+ public NetworkStats insertEntry(String iface, int uid, int set, int tag, int metered,
+ int roaming, int defaultNetwork, long rxBytes, long rxPackets, long txBytes,
+ long txPackets, long operations) {
+ return insertEntry(new Entry(
iface, uid, set, tag, metered, roaming, defaultNetwork, rxBytes, rxPackets,
txBytes, txPackets, operations));
}
@@ -522,7 +559,7 @@
* object can be recycled across multiple calls.
* @hide
*/
- public NetworkStats addEntry(Entry entry) {
+ public NetworkStats insertEntry(Entry entry) {
if (size >= capacity) {
final int newLength = Math.max(size, 10) * 3 / 2;
iface = Arrays.copyOf(iface, newLength);
@@ -665,7 +702,7 @@
entry.roaming, entry.defaultNetwork);
if (i == -1) {
// only create new entry when positive contribution
- addEntry(entry);
+ insertEntry(entry);
} else {
rxBytes[i] += entry.rxBytes;
rxPackets[i] += entry.rxPackets;
@@ -684,7 +721,7 @@
* @param entry the {@link Entry} to add.
* @return a new constructed {@link NetworkStats} object that contains the result.
*/
- public @NonNull NetworkStats addValues(@NonNull Entry entry) {
+ public @NonNull NetworkStats addEntry(@NonNull Entry entry) {
return this.clone().combineValues(entry);
}
@@ -1003,7 +1040,7 @@
entry.operations = Math.max(entry.operations, 0);
}
- result.addEntry(entry);
+ result.insertEntry(entry);
}
return result;
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 5498f74..cb9463a 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -34,9 +34,13 @@
import static android.net.NetworkStats.ROAMING_YES;
import static android.net.wifi.WifiInfo.sanitizeSsid;
+import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.Annotation.NetworkType;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.BackupUtils;
import android.util.Log;
@@ -73,6 +77,14 @@
public static final int MATCH_BLUETOOTH = 8;
public static final int MATCH_PROXY = 9;
+ /**
+ * Include all network types when filtering. This is meant to merge in with the
+ * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync.
+ *
+ * @hide
+ */
+ public static final int NETWORK_TYPE_ALL = -1;
+
private static boolean isKnownMatchRule(final int rule) {
switch (rule) {
case MATCH_MOBILE:
@@ -117,7 +129,22 @@
}
/**
- * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks,
+ * Template to match cellular networks with the given IMSI and {@code ratType}.
+ * Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering.
+ * See {@code TelephonyManager.NETWORK_TYPE_*}.
+ */
+ public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
+ @NetworkType int ratType) {
+ if (TextUtils.isEmpty(subscriberId)) {
+ return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null,
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType);
+ }
+ return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null,
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType);
+ }
+
+ /**
+ * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks,
* regardless of IMSI.
*/
@UnsupportedAppUsage
@@ -126,7 +153,7 @@
}
/**
- * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks,
+ * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks,
* regardless of SSID.
*/
@UnsupportedAppUsage
@@ -192,6 +219,7 @@
private final int mMetered;
private final int mRoaming;
private final int mDefaultNetwork;
+ private final int mSubType;
@UnsupportedAppUsage
public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
@@ -201,11 +229,11 @@
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
String networkId) {
this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL);
+ DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL);
}
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
- String networkId, int metered, int roaming, int defaultNetwork) {
+ String networkId, int metered, int roaming, int defaultNetwork, int subType) {
mMatchRule = matchRule;
mSubscriberId = subscriberId;
mMatchSubscriberIds = matchSubscriberIds;
@@ -213,6 +241,7 @@
mMetered = metered;
mRoaming = roaming;
mDefaultNetwork = defaultNetwork;
+ mSubType = subType;
if (!isKnownMatchRule(matchRule)) {
Log.e(TAG, "Unknown network template rule " + matchRule
@@ -228,6 +257,7 @@
mMetered = in.readInt();
mRoaming = in.readInt();
mDefaultNetwork = in.readInt();
+ mSubType = in.readInt();
}
@Override
@@ -239,6 +269,7 @@
dest.writeInt(mMetered);
dest.writeInt(mRoaming);
dest.writeInt(mDefaultNetwork);
+ dest.writeInt(mSubType);
}
@Override
@@ -271,13 +302,16 @@
builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString(
mDefaultNetwork));
}
+ if (mSubType != NETWORK_TYPE_ALL) {
+ builder.append(", subType=").append(mSubType);
+ }
return builder.toString();
}
@Override
public int hashCode() {
return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming,
- mDefaultNetwork);
+ mDefaultNetwork, mSubType);
}
@Override
@@ -289,7 +323,8 @@
&& Objects.equals(mNetworkId, other.mNetworkId)
&& mMetered == other.mMetered
&& mRoaming == other.mRoaming
- && mDefaultNetwork == other.mDefaultNetwork;
+ && mDefaultNetwork == other.mDefaultNetwork
+ && mSubType == other.mSubType;
}
return false;
}
@@ -376,6 +411,11 @@
|| (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork);
}
+ private boolean matchesCollapsedRatType(NetworkIdentity ident) {
+ return mSubType == NETWORK_TYPE_ALL
+ || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType);
+ }
+
public boolean matchesSubscriberId(String subscriberId) {
return ArrayUtils.contains(mMatchSubscriberIds, subscriberId);
}
@@ -388,9 +428,52 @@
// TODO: consider matching against WiMAX subscriber identity
return true;
} else {
+ // Only metered mobile network would be matched regardless of metered filter.
+ // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650.
+ // TODO: Respect metered filter and remove mMetered condition.
return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
&& !ArrayUtils.isEmpty(mMatchSubscriberIds)
- && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
+ && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
+ && matchesCollapsedRatType(ident);
+ }
+ }
+
+ /**
+ * Get a Radio Access Technology(RAT) type that is representative of a group of RAT types.
+ * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}.
+ *
+ * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
+ */
+ // TODO: 1. Consider move this to TelephonyManager if used by other modules.
+ // 2. Consider make this configurable.
+ // 3. Use TelephonyManager APIs when available.
+ public static int getCollapsedRatType(int ratType) {
+ switch (ratType) {
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_GSM:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_IDEN:
+ case TelephonyManager.NETWORK_TYPE_CDMA:
+ case TelephonyManager.NETWORK_TYPE_1xRTT:
+ return TelephonyManager.NETWORK_TYPE_GSM;
+ case TelephonyManager.NETWORK_TYPE_EVDO_0:
+ case TelephonyManager.NETWORK_TYPE_EVDO_A:
+ case TelephonyManager.NETWORK_TYPE_EVDO_B:
+ case TelephonyManager.NETWORK_TYPE_EHRPD:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+ return TelephonyManager.NETWORK_TYPE_UMTS;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ case TelephonyManager.NETWORK_TYPE_IWLAN:
+ return TelephonyManager.NETWORK_TYPE_LTE;
+ case TelephonyManager.NETWORK_TYPE_NR:
+ return TelephonyManager.NETWORK_TYPE_NR;
+ default:
+ return TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
}
@@ -421,7 +504,8 @@
if (ident.mType == TYPE_WIMAX) {
return true;
} else {
- return sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered);
+ return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
+ && matchesCollapsedRatType(ident);
}
}
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 2b9e9fe..fec2df4 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -527,6 +527,26 @@
}
/**
+ * Compares this RouteInfo object against the specified object and indicates if the
+ * destinations of both routes are equal.
+ * @return {@code true} if the route destinations are equal, {@code false} otherwise.
+ *
+ * @hide
+ */
+ public boolean isSameDestinationAs(@Nullable Object obj) {
+ if (this == obj) return true;
+
+ if (!(obj instanceof RouteInfo)) return false;
+
+ RouteInfo target = (RouteInfo) obj;
+
+ if (Objects.equals(mDestination, target.getDestination())) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Returns a hashcode for this <code>RouteInfo</code> object.
*/
public int hashCode() {
diff --git a/core/java/android/net/TestNetworkManager.java b/core/java/android/net/TestNetworkManager.java
index 4ac4a69..c3284df 100644
--- a/core/java/android/net/TestNetworkManager.java
+++ b/core/java/android/net/TestNetworkManager.java
@@ -16,6 +16,7 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.TestApi;
import android.os.IBinder;
import android.os.RemoteException;
@@ -53,6 +54,19 @@
}
}
+ private void setupTestNetwork(
+ @NonNull String iface,
+ @Nullable LinkProperties lp,
+ boolean isMetered,
+ @NonNull int[] administratorUids,
+ @NonNull IBinder binder) {
+ try {
+ mService.setupTestNetwork(iface, lp, isMetered, administratorUids, binder);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* Sets up a capability-limited, testing-only network for a given interface
*
@@ -66,11 +80,7 @@
public void setupTestNetwork(
@NonNull LinkProperties lp, boolean isMetered, @NonNull IBinder binder) {
Preconditions.checkNotNull(lp, "Invalid LinkProperties");
- try {
- mService.setupTestNetwork(lp.getInterfaceName(), lp, isMetered, binder);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ setupTestNetwork(lp.getInterfaceName(), lp, isMetered, new int[0], binder);
}
/**
@@ -82,11 +92,21 @@
*/
@TestApi
public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) {
- try {
- mService.setupTestNetwork(iface, null, true, binder);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ setupTestNetwork(iface, null, true, new int[0], binder);
+ }
+
+ /**
+ * Sets up a capability-limited, testing-only network for a given interface with the given
+ * administrator UIDs.
+ *
+ * @param iface the name of the interface to be used for the Network LinkProperties.
+ * @param administratorUids The administrator UIDs to be used for the test-only network
+ * @param binder A binder object guarding the lifecycle of this test network.
+ * @hide
+ */
+ public void setupTestNetwork(
+ @NonNull String iface, @NonNull int[] administratorUids, @NonNull IBinder binder) {
+ setupTestNetwork(iface, null, true, administratorUids, binder);
}
/**
diff --git a/core/java/android/net/netstats/provider/AbstractNetworkStatsProvider.java b/core/java/android/net/netstats/provider/AbstractNetworkStatsProvider.java
deleted file mode 100644
index 740aa92..0000000
--- a/core/java/android/net/netstats/provider/AbstractNetworkStatsProvider.java
+++ /dev/null
@@ -1,70 +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.net.netstats.provider;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.net.NetworkStats;
-
-/**
- * A base class that allows external modules to implement a custom network statistics provider.
- * @hide
- */
-@SystemApi
-public abstract class AbstractNetworkStatsProvider {
- /**
- * A value used by {@link #setLimit} and {@link #setAlert} indicates there is no limit.
- */
- public static final int QUOTA_UNLIMITED = -1;
-
- /**
- * Called by {@code NetworkStatsService} when global polling is needed. Custom
- * implementation of providers MUST respond to it by calling
- * {@link NetworkStatsProviderCallback#onStatsUpdated} within one minute. Responding
- * later than this may cause the stats to be dropped.
- *
- * @param token a positive number identifying the new state of the system under which
- * {@link NetworkStats} have to be gathered from now on. When this is called,
- * custom implementations of providers MUST report the latest stats with the
- * previous token, under which stats were being gathered so far.
- */
- public abstract void requestStatsUpdate(int token);
-
- /**
- * Called by {@code NetworkStatsService} when setting the interface quota for the specified
- * upstream interface. When this is called, the custom implementation should block all egress
- * packets on the {@code iface} associated with the provider when {@code quotaBytes} bytes have
- * been reached, and MUST respond to it by calling
- * {@link NetworkStatsProviderCallback#onLimitReached()}.
- *
- * @param iface the interface requiring the operation.
- * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
- * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit.
- */
- public abstract void setLimit(@NonNull String iface, long quotaBytes);
-
- /**
- * Called by {@code NetworkStatsService} when setting the alert bytes. Custom implementations
- * MUST call {@link NetworkStatsProviderCallback#onAlertReached()} when {@code quotaBytes} bytes
- * have been reached. Unlike {@link #setLimit(String, long)}, the custom implementation should
- * not block all egress packets.
- *
- * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
- * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no alert.
- */
- public abstract void setAlert(long quotaBytes);
-}
diff --git a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl
index 55b3d4e..4078b24 100644
--- a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl
+++ b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl
@@ -22,7 +22,7 @@
* @hide
*/
oneway interface INetworkStatsProvider {
- void requestStatsUpdate(int token);
- void setLimit(String iface, long quotaBytes);
- void setAlert(long quotaBytes);
+ void onRequestStatsUpdate(int token);
+ void onSetLimit(String iface, long quotaBytes);
+ void onSetAlert(long quotaBytes);
}
diff --git a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
index 3ea9318..bd336dd 100644
--- a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
+++ b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl
@@ -24,8 +24,8 @@
* @hide
*/
oneway interface INetworkStatsProviderCallback {
- void onStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats);
- void onAlertReached();
- void onLimitReached();
+ void notifyStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats);
+ void notifyAlertReached();
+ void notifyLimitReached();
void unregister();
}
diff --git a/core/java/android/net/netstats/provider/NetworkStatsProvider.java b/core/java/android/net/netstats/provider/NetworkStatsProvider.java
new file mode 100644
index 0000000..7639d22
--- /dev/null
+++ b/core/java/android/net/netstats/provider/NetworkStatsProvider.java
@@ -0,0 +1,195 @@
+/*
+ * 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.net.netstats.provider;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.net.NetworkStats;
+import android.os.RemoteException;
+
+/**
+ * A base class that allows external modules to implement a custom network statistics provider.
+ * @hide
+ */
+@SystemApi
+public abstract class NetworkStatsProvider {
+ /**
+ * A value used by {@link #onSetLimit} and {@link #onSetAlert} indicates there is no limit.
+ */
+ public static final int QUOTA_UNLIMITED = -1;
+
+ @NonNull private final INetworkStatsProvider mProviderBinder =
+ new INetworkStatsProvider.Stub() {
+
+ @Override
+ public void onRequestStatsUpdate(int token) {
+ NetworkStatsProvider.this.onRequestStatsUpdate(token);
+ }
+
+ @Override
+ public void onSetLimit(String iface, long quotaBytes) {
+ NetworkStatsProvider.this.onSetLimit(iface, quotaBytes);
+ }
+
+ @Override
+ public void onSetAlert(long quotaBytes) {
+ NetworkStatsProvider.this.onSetAlert(quotaBytes);
+ }
+ };
+
+ // The binder given by the service when successfully registering. Only null before registering,
+ // never null once non-null.
+ @Nullable
+ private INetworkStatsProviderCallback mProviderCbBinder;
+
+ /**
+ * Return the binder invoked by the service and redirect function calls to the overridden
+ * methods.
+ * @hide
+ */
+ @NonNull
+ public INetworkStatsProvider getProviderBinder() {
+ return mProviderBinder;
+ }
+
+ /**
+ * Store the binder that was returned by the service when successfully registering. Note that
+ * the provider cannot be re-registered. Hence this method can only be called once per provider.
+ *
+ * @hide
+ */
+ public void setProviderCallbackBinder(@NonNull INetworkStatsProviderCallback binder) {
+ if (mProviderCbBinder != null) {
+ throw new IllegalArgumentException("provider is already registered");
+ }
+ mProviderCbBinder = binder;
+ }
+
+ /**
+ * Get the binder that was returned by the service when successfully registering. Or null if the
+ * provider was never registered.
+ *
+ * @hide
+ */
+ @Nullable
+ public INetworkStatsProviderCallback getProviderCallbackBinder() {
+ return mProviderCbBinder;
+ }
+
+ /**
+ * Get the binder that was returned by the service when successfully registering. Throw an
+ * {@link IllegalStateException} if the provider is not registered.
+ *
+ * @hide
+ */
+ @NonNull
+ public INetworkStatsProviderCallback getProviderCallbackBinderOrThrow() {
+ if (mProviderCbBinder == null) {
+ throw new IllegalStateException("the provider is not registered");
+ }
+ return mProviderCbBinder;
+ }
+
+ /**
+ * Notify the system of new network statistics.
+ *
+ * Send the network statistics recorded since the last call to {@link #notifyStatsUpdated}. Must
+ * be called as soon as possible after {@link NetworkStatsProvider#onRequestStatsUpdate(int)}
+ * being called. Responding later increases the probability stats will be dropped. The
+ * provider can also call this whenever it wants to reports new stats for any reason.
+ * Note that the system will not necessarily immediately propagate the statistics to
+ * reflect the update.
+ *
+ * @param token the token under which these stats were gathered. Providers can call this method
+ * with the current token as often as they want, until the token changes.
+ * {@see NetworkStatsProvider#onRequestStatsUpdate()}
+ * @param ifaceStats the {@link NetworkStats} per interface to be reported.
+ * The provider should not include any traffic that is already counted by
+ * kernel interface counters.
+ * @param uidStats the same stats as above, but counts {@link NetworkStats}
+ * per uid.
+ */
+ public void notifyStatsUpdated(int token, @NonNull NetworkStats ifaceStats,
+ @NonNull NetworkStats uidStats) {
+ try {
+ getProviderCallbackBinderOrThrow().notifyStatsUpdated(token, ifaceStats, uidStats);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Notify system that the quota set by {@code onSetAlert} has been reached.
+ */
+ public void notifyAlertReached() {
+ try {
+ getProviderCallbackBinderOrThrow().notifyAlertReached();
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Notify system that the quota set by {@code onSetLimit} has been reached.
+ */
+ public void notifyLimitReached() {
+ try {
+ getProviderCallbackBinderOrThrow().notifyLimitReached();
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Called by {@code NetworkStatsService} when it requires to know updated stats.
+ * The provider MUST respond by calling {@link #notifyStatsUpdated} as soon as possible.
+ * Responding later increases the probability stats will be dropped. Memory allowing, the
+ * system will try to take stats into account up to one minute after calling
+ * {@link #onRequestStatsUpdate}.
+ *
+ * @param token a positive number identifying the new state of the system under which
+ * {@link NetworkStats} have to be gathered from now on. When this is called,
+ * custom implementations of providers MUST tally and report the latest stats with
+ * the previous token, under which stats were being gathered so far.
+ */
+ public abstract void onRequestStatsUpdate(int token);
+
+ /**
+ * Called by {@code NetworkStatsService} when setting the interface quota for the specified
+ * upstream interface. When this is called, the custom implementation should block all egress
+ * packets on the {@code iface} associated with the provider when {@code quotaBytes} bytes have
+ * been reached, and MUST respond to it by calling
+ * {@link NetworkStatsProvider#notifyLimitReached()}.
+ *
+ * @param iface the interface requiring the operation.
+ * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
+ * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit.
+ */
+ public abstract void onSetLimit(@NonNull String iface, long quotaBytes);
+
+ /**
+ * Called by {@code NetworkStatsService} when setting the alert bytes. Custom implementations
+ * MUST call {@link NetworkStatsProvider#notifyAlertReached()} when {@code quotaBytes} bytes
+ * have been reached. Unlike {@link #onSetLimit(String, long)}, the custom implementation should
+ * not block all egress packets.
+ *
+ * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
+ * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no alert.
+ */
+ public abstract void onSetAlert(long quotaBytes);
+}
diff --git a/core/java/android/net/netstats/provider/NetworkStatsProviderCallback.java b/core/java/android/net/netstats/provider/NetworkStatsProviderCallback.java
deleted file mode 100644
index e17a8ee..0000000
--- a/core/java/android/net/netstats/provider/NetworkStatsProviderCallback.java
+++ /dev/null
@@ -1,98 +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.net.netstats.provider;
-
-import android.annotation.NonNull;
-import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
-import android.net.NetworkStats;
-import android.os.RemoteException;
-
-/**
- * A callback class that allows callers to report events to the system.
- * @hide
- */
-@SystemApi
-@SuppressLint("CallbackMethodName")
-public class NetworkStatsProviderCallback {
- @NonNull private final INetworkStatsProviderCallback mBinder;
-
- /** @hide */
- public NetworkStatsProviderCallback(@NonNull INetworkStatsProviderCallback binder) {
- mBinder = binder;
- }
-
- /**
- * Notify the system of new network statistics.
- *
- * Send the network statistics recorded since the last call to {@link #onStatsUpdated}. Must be
- * called within one minute of {@link AbstractNetworkStatsProvider#requestStatsUpdate(int)}
- * being called. The provider can also call this whenever it wants to reports new stats for any
- * reason. Note that the system will not necessarily immediately propagate the statistics to
- * reflect the update.
- *
- * @param token the token under which these stats were gathered. Providers can call this method
- * with the current token as often as they want, until the token changes.
- * {@see AbstractNetworkStatsProvider#requestStatsUpdate()}
- * @param ifaceStats the {@link NetworkStats} per interface to be reported.
- * The provider should not include any traffic that is already counted by
- * kernel interface counters.
- * @param uidStats the same stats as above, but counts {@link NetworkStats}
- * per uid.
- */
- public void onStatsUpdated(int token, @NonNull NetworkStats ifaceStats,
- @NonNull NetworkStats uidStats) {
- try {
- mBinder.onStatsUpdated(token, ifaceStats, uidStats);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- }
-
- /**
- * Notify system that the quota set by {@code setAlert} has been reached.
- */
- public void onAlertReached() {
- try {
- mBinder.onAlertReached();
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- }
-
- /**
- * Notify system that the quota set by {@code setLimit} has been reached.
- */
- public void onLimitReached() {
- try {
- mBinder.onLimitReached();
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- }
-
- /**
- * Unregister the provider and the referencing callback.
- */
- public void unregister() {
- try {
- mBinder.unregister();
- } catch (RemoteException e) {
- // Ignore error.
- }
- }
-}
diff --git a/core/java/android/net/netstats/provider/NetworkStatsProviderWrapper.java b/core/java/android/net/netstats/provider/NetworkStatsProviderWrapper.java
deleted file mode 100644
index 4bf7c9b..0000000
--- a/core/java/android/net/netstats/provider/NetworkStatsProviderWrapper.java
+++ /dev/null
@@ -1,48 +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.net.netstats.provider;
-
-import android.annotation.NonNull;
-
-/**
- * A wrapper class of {@link INetworkStatsProvider} that hides the binder interface from exposing
- * to outer world.
- *
- * @hide
- */
-public class NetworkStatsProviderWrapper extends INetworkStatsProvider.Stub {
- @NonNull final AbstractNetworkStatsProvider mProvider;
-
- public NetworkStatsProviderWrapper(AbstractNetworkStatsProvider provider) {
- mProvider = provider;
- }
-
- @Override
- public void requestStatsUpdate(int token) {
- mProvider.requestStatsUpdate(token);
- }
-
- @Override
- public void setLimit(@NonNull String iface, long quotaBytes) {
- mProvider.setLimit(iface, quotaBytes);
- }
-
- @Override
- public void setAlert(long quotaBytes) {
- mProvider.setAlert(quotaBytes);
- }
-}
diff --git a/core/java/android/net/util/SocketUtils.java b/core/java/android/net/util/SocketUtils.java
index e9ea99f..6967084 100644
--- a/core/java/android/net/util/SocketUtils.java
+++ b/core/java/android/net/util/SocketUtils.java
@@ -66,6 +66,10 @@
/**
* Make socket address that packet sockets can bind to.
+ *
+ * @param protocol the layer 2 protocol of the packets to receive. One of the {@code ETH_P_*}
+ * constants in {@link android.system.OsConstants}.
+ * @param ifIndex the interface index on which packets will be received.
*/
@NonNull
public static SocketAddress makePacketSocketAddress(int protocol, int ifIndex) {
@@ -78,6 +82,9 @@
/**
* Make a socket address that packet socket can send packets to.
* @deprecated Use {@link #makePacketSocketAddress(int, int, byte[])} instead.
+ *
+ * @param ifIndex the interface index on which packets will be sent.
+ * @param hwAddr the hardware address to which packets will be sent.
*/
@Deprecated
@NonNull
@@ -89,7 +96,12 @@
}
/**
- * Make a socket address that packet socket can send packets to.
+ * Make a socket address that a packet socket can send packets to.
+ *
+ * @param protocol the layer 2 protocol of the packets to send. One of the {@code ETH_P_*}
+ * constants in {@link android.system.OsConstants}.
+ * @param ifIndex the interface index on which packets will be sent.
+ * @param hwAddr the hardware address to which packets will be sent.
*/
@NonNull
public static SocketAddress makePacketSocketAddress(int protocol, int ifIndex,
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index d320f61..c61f10f 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -245,13 +245,25 @@
/**
* Mandatory String extra field in {@link #ACTION_PREFERRED_PAYMENT_CHANGED}
- * Indicates the condition when trigger this event.
+ * Indicates the condition when trigger this event. Possible values are:
+ * {@link #PREFERRED_PAYMENT_LOADED},
+ * {@link #PREFERRED_PAYMENT_CHANGED},
+ * {@link #PREFERRED_PAYMENT_UPDATED},
*/
public static final String EXTRA_PREFERRED_PAYMENT_CHANGED_REASON =
"android.nfc.extra.PREFERRED_PAYMENT_CHANGED_REASON";
-
+ /**
+ * Nfc is enabled and the preferred payment aids are registered.
+ */
public static final int PREFERRED_PAYMENT_LOADED = 1;
+ /**
+ * User selected another payment application as the preferred payment.
+ */
public static final int PREFERRED_PAYMENT_CHANGED = 2;
+ /**
+ * Current preferred payment has issued an update (registered/unregistered new aids or has been
+ * updated itself).
+ */
public static final int PREFERRED_PAYMENT_UPDATED = 3;
public static final int STATE_OFF = 1;
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index f1c74a6..7bf82e8 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -672,7 +672,7 @@
recoverService();
if (sService == null) {
Log.e(TAG, "Failed to recover CardEmulationService.");
- return null;
+ throw e.rethrowFromSystemServer();
}
try {
ApduServiceInfo serviceInfo =
@@ -680,7 +680,7 @@
return (serviceInfo != null ? serviceInfo.getAids() : null);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to recover CardEmulationService.");
- return null;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -690,9 +690,16 @@
*
* @return The route destination secure element name of the preferred payment service.
* HCE payment: "Host"
- * OffHost payment: prefix SIM or prefix eSE string.
- * "OffHost" if the payment service does not specify secure element
- * name.
+ * OffHost payment: 1. String with prefix SIM or prefix eSE string.
+ * Ref: GSMA TS.26 - NFC Handset Requirements
+ * TS26_NFC_REQ_069: For UICC, Secure Element Name SHALL be
+ * SIM[smartcard slot]
+ * (e.g. SIM/SIM1, SIM2… SIMn).
+ * TS26_NFC_REQ_070: For embedded SE, Secure Element Name SHALL be
+ * eSE[number]
+ * (e.g. eSE/eSE1, eSE2, etc.).
+ * 2. "OffHost" if the payment service does not specify secure element
+ * name.
*/
@RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
@Nullable
@@ -711,7 +718,7 @@
recoverService();
if (sService == null) {
Log.e(TAG, "Failed to recover CardEmulationService.");
- return null;
+ throw e.rethrowFromSystemServer();
}
try {
ApduServiceInfo serviceInfo =
@@ -727,7 +734,7 @@
} catch (RemoteException ee) {
Log.e(TAG, "Failed to recover CardEmulationService.");
- return null;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -739,7 +746,7 @@
*/
@RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO)
@Nullable
- public String getDescriptionForPreferredPaymentService() {
+ public CharSequence getDescriptionForPreferredPaymentService() {
try {
ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(mContext.getUserId());
return (serviceInfo != null ? serviceInfo.getDescription() : null);
@@ -747,7 +754,7 @@
recoverService();
if (sService == null) {
Log.e(TAG, "Failed to recover CardEmulationService.");
- return null;
+ throw e.rethrowFromSystemServer();
}
try {
ApduServiceInfo serviceInfo =
@@ -755,7 +762,7 @@
return (serviceInfo != null ? serviceInfo.getDescription() : null);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to recover CardEmulationService.");
- return null;
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/os/ConfigUpdate.java b/core/java/android/os/ConfigUpdate.java
index 590fbb3..a28f5fb 100644
--- a/core/java/android/os/ConfigUpdate.java
+++ b/core/java/android/os/ConfigUpdate.java
@@ -17,6 +17,8 @@
package android.os;
import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
/**
@@ -125,6 +127,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.UPDATE_CONFIG)
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_UPDATE_EMERGENCY_NUMBER_DB =
"android.os.action.UPDATE_EMERGENCY_NUMBER_DB";
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 09ccb72..ae65f1d 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -24,6 +24,8 @@
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.Disabled;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
@@ -90,13 +92,43 @@
"/apex");
/**
- * See definition in com.android.providers.media.LocalCallingIdentity
+ * Scoped Storage is on by default. However, it is not strictly enforced and there are multiple
+ * ways to opt out of scoped storage:
+ * <ul>
+ * <li>Target Sdk < Q</li>
+ * <li>Target Sdk = Q and has `requestLegacyExternalStorage` set in AndroidManifest.xml</li>
+ * <li>Target Sdk > Q: Upgrading from an app that was opted out of scoped storage and has
+ * `preserveLegacyExternalStorage` set in AndroidManifest.xml</li>
+ * </ul>
+ * This flag is enabled for all apps by default as Scoped Storage is enabled by default.
+ * Developers can disable this flag to opt out of Scoped Storage and have legacy storage
+ * workflow.
+ *
+ * Note: {@code FORCE_ENABLE_SCOPED_STORAGE} should also be disabled for apps to opt out of
+ * scoped storage.
+ * Note: This flag is also used in {@code com.android.providers.media.LocalCallingIdentity}.
+ * Any modifications to this flag should be reflected there as well.
+ * See https://developer.android.com/training/data-storage#scoped-storage for more information.
*/
+ @ChangeId
private static final long DEFAULT_SCOPED_STORAGE = 149924527L;
/**
- * See definition in com.android.providers.media.LocalCallingIdentity
+ * Setting this flag strictly enforces Scoped Storage regardless of:
+ * <ul>
+ * <li>The value of Target Sdk</li>
+ * <li>The value of `requestLegacyExternalStorage` in AndroidManifest.xml</li>
+ * <li>The value of `preserveLegacyExternalStorage` in AndroidManifest.xml</li>
+ * </ul>
+ *
+ * Note: {@code DEFAULT_SCOPED_STORAGE} should also be enabled for apps to be enforced into
+ * scoped storage.
+ * Note: This flag is also used in {@code com.android.providers.media.LocalCallingIdentity}.
+ * Any modifications to this flag should be reflected there as well.
+ * See https://developer.android.com/training/data-storage#scoped-storage for more information.
*/
+ @ChangeId
+ @Disabled
private static final long FORCE_ENABLE_SCOPED_STORAGE = 132649864L;
@UnsupportedAppUsage
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index a557bd9..b7b3c4f 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -931,6 +931,19 @@
public static final native void setProcessFrozen(int pid, int uid, boolean frozen);
/**
+ * Enable or disable the freezer. When enable == false all frozen processes are unfrozen,
+ * but aren't removed from the freezer. Processes can still be added or removed
+ * by using setProcessFrozen, but they won't actually be frozen until the freezer is enabled
+ * again. If enable == true the freezer is enabled again, and all processes
+ * in the freezer (including the ones added while the freezer was disabled) are frozen.
+ *
+ * @param enable Specify whether to enable (true) or disable (false) the freezer.
+ *
+ * @hide
+ */
+ public static final native void enableFreezer(boolean enable);
+
+ /**
* Return the scheduling group of requested process.
*
* @hide
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index f43a252..e05991b 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -144,4 +144,10 @@
* @param uid the uid of the package
*/
public abstract void prepareAppDataAfterInstall(@NonNull String packageName, int uid);
+
+
+ /**
+ * Return true if uid is external storage service.
+ */
+ public abstract boolean isExternalStorageService(int uid);
}
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index 4a42230..82a7d78 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -58,6 +58,7 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
@@ -214,6 +215,7 @@
@BinderThread
public abstract void onGrantOrUpgradeDefaultRuntimePermissions(@NonNull Runnable callback);
+
/**
* Called by system to update the
* {@link PackageManager}{@code .FLAG_PERMISSION_USER_SENSITIVE_WHEN_*} flags for permissions.
@@ -223,10 +225,22 @@
*
* Typically called by the system when a new app is installed or updated or when creating a
* new user or upgrading either system or permission controller package.
+ *
+ * The callback will be executed by the provided Executor.
+ */
+ @BinderThread
+ public void onUpdateUserSensitivePermissionFlags(int uid, @NonNull Executor executor,
+ @NonNull Runnable callback) {
+ throw new AbstractMethodError("Must be overridden in implementing class");
+ }
+
+ /**
+ * Runs {@link #onUpdateUserSensitivePermissionFlags(int, Executor, Runnable)} with the main
+ * executor.
*/
@BinderThread
public void onUpdateUserSensitivePermissionFlags(int uid, @NonNull Runnable callback) {
- throw new AbstractMethodError("Must be overridden in implementing class");
+ onUpdateUserSensitivePermissionFlags(uid, getMainExecutor(), callback);
}
/**
diff --git a/core/java/android/permission/Permissions.md b/core/java/android/permission/Permissions.md
index e62bd0a..e116dc6 100644
--- a/core/java/android/permission/Permissions.md
+++ b/core/java/android/permission/Permissions.md
@@ -49,6 +49,10 @@
to involve the user. This can be either because the API is not sensitive, or because additional
checks exist.
+Another benefit of install time permissions is that is becomes very easy to monitor which apps can
+access certain APIs. E.g. by checking which apps have the `android.permission.INTERNET` permission
+you can list all apps that are allowed to use APIs that can send data to the internet.
+
#### Defining a permission
Any package can define a permission. For that it simply adds an entry in the manifest file
@@ -591,8 +595,9 @@
### Permission restricted components
As [publicly documented](https://developer.android.com/guide/topics/permissions/overview#permission_enforcement)
-it is possible to restrict starting an activity/binding to a service by using permission. It is
-a common pattern to
+it is possible to restrict starting an activity/binding to a service by using permission.
+
+It is a common pattern to
- define a permission in the platform as `signature`
- protect a service in an app by this permission using the `android:permission` attribute of the
@@ -605,6 +610,75 @@
This does not work for app-op or runtime permissions as the way to check these permissions is
more complex than install time permissions.
+#### End-to-end A service only the system can bind to
+
+Make sure to set the `android:permission` flag for this service. As developers can forget this it is
+a good habit to check this before binding to the service. This makes sure that the services are
+implemented correctly and no random app can bind to the service.
+
+The result is that the permission is granted only to the system. It is not granted to the service's
+package, but this has no negative side-effects.
+
+##### Permission definition
+
+frameworks/base/core/res/AndroidManifest.xml:
+
+```xml
+<manifest>
+[...]
+ <permission android:name="android.permission.BIND_MY_SERVICE"
+ android:label="@string/permlab_bindMyService"
+ android:description="@string/permdesc_bindMyService"
+ android:protectionLevel="signature" />
+[...]
+</manifest>
+```
+
+##### Service definition
+
+Manifest of the service providing the functionality:
+
+```xml
+<manifest>
+ <service android:name="com.my.ServiceImpl"
+ android:permission="android.permission.BIND_MY_SERVICE">
+ <!-- add an intent filter so that the system can find this package -->
+ <intent-filter>
+ <action android:name="android.my.Service" />
+ </intent-filter>
+ </service>
+</manifest>
+```
+
+##### System server code binding to service
+
+```kotlin
+val serviceConnections = mutableListOf<ServiceConnection>()
+
+val potentialServices = context.packageManager.queryIntentServicesAsUser(
+ Intent("android.my.Service"), GET_SERVICES or GET_META_DATA, userId)
+
+for (val ri in potentialServices) {
+ val serviceComponent = ComponentName(ri.serviceInfo.packageName, ri.serviceInfo.name)
+
+ if (android.Manifest.permission.BIND_MY_SERVICE != ri.serviceInfo.permission) {
+ Slog.w(TAG, "$serviceComponent is not protected by " +
+ "${android.Manifest.permission.BIND_MY_SERVICE}")
+ continue
+ }
+
+ val newConnection = object : ServiceConnection {
+ ...
+ }
+
+ val wasBound = context.bindServiceAsUser(Intent().setComponent(serviceComponent),
+ serviceConnection, BIND_AUTO_CREATE, UserHandle.of(userId))
+ if (wasBound) {
+ serviceConnections.add(newConnection)
+ }
+}
+```
+
## Permissions for system apps
System apps need to integrate deeper with the system than regular apps. Hence they need to be
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d8679b20..789b8d1 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9718,6 +9718,8 @@
public static final String NETSTATS_SAMPLE_ENABLED = "netstats_sample_enabled";
/** {@hide} */
public static final String NETSTATS_AUGMENT_ENABLED = "netstats_augment_enabled";
+ /** {@hide} */
+ public static final String NETSTATS_COMBINE_SUBTYPE_ENABLED = "netstats_combine_subtype_enabled";
/** {@hide} */
public static final String NETSTATS_DEV_BUCKET_DURATION = "netstats_dev_bucket_duration";
@@ -14192,19 +14194,6 @@
"power_button_suppression_delay_after_gesture_wake";
/**
- * An integer indicating whether the device is in Common Criteria mode. When enabled,
- * certain device functionalities are tuned to meet the higher security level required
- * by Common Criteria certification. Examples include:
- * Bluetooth long term key material is additionally integrity-protected with AES-GCM.
- * WiFi configuration store is additionally integrity-protected with AES-GCM.
- * A value of 0 means Common Criteria mode is not enabled (default), a value of non-zero
- * means Common Criteria mode is enabled.
- * @hide
- */
- @SystemApi
- public static final String COMMON_CRITERIA_MODE = "common_criteria_mode";
-
- /**
* The usage amount of advanced battery. The value is 0~100.
*
* @hide
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index e7b360d..17e3748 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1391,7 +1391,6 @@
* Base column for the table that contain Carrier Public key.
* @hide
*/
- @SystemApi
public interface CarrierColumns extends BaseColumns {
/**
@@ -4704,7 +4703,6 @@
* Contains mappings between matching rules with carrier id for all carriers.
* @hide
*/
- @SystemApi
public static final class All implements BaseColumns {
/**
diff --git a/core/java/android/se/omapi/Reader.java b/core/java/android/se/omapi/Reader.java
index 7f68d91..90c934d 100644
--- a/core/java/android/se/omapi/Reader.java
+++ b/core/java/android/se/omapi/Reader.java
@@ -160,7 +160,7 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.SECURE_ELEMENT_PRIVILEGED)
+ @RequiresPermission(android.Manifest.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION)
public boolean reset() {
if (!mService.isConnected()) {
Log.e(TAG, "service is not connected");
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 06b5fa0..bc08b84 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -88,8 +88,6 @@
private final @Nullable UserData mUserData;
private final @Nullable int[] mCancelIds;
private final boolean mSupportsInlineSuggestions;
- // TODO(b/149240554): revert back to use ParceledListSlice after the bug is resolved.
- private final @Nullable ArrayList<InlineAction> mInlineActions;
private FillResponse(@NonNull Builder builder) {
mDatasets = (builder.mDatasets != null) ? new ParceledListSlice<>(builder.mDatasets) : null;
@@ -109,7 +107,6 @@
mUserData = builder.mUserData;
mCancelIds = builder.mCancelIds;
mSupportsInlineSuggestions = builder.mSupportsInlineSuggestions;
- mInlineActions = builder.mInlineActions;
}
/** @hide */
@@ -212,11 +209,6 @@
return mSupportsInlineSuggestions;
}
- /** @hide */
- public @Nullable List<InlineAction> getInlineActions() {
- return mInlineActions;
- }
-
/**
* Builder for {@link FillResponse} objects. You must to provide at least
* one dataset or set an authentication intent with a presentation view.
@@ -239,7 +231,6 @@
private UserData mUserData;
private int[] mCancelIds;
private boolean mSupportsInlineSuggestions;
- private ArrayList<InlineAction> mInlineActions;
/**
* Triggers a custom UI before before autofilling the screen with any data set in this
@@ -656,22 +647,6 @@
}
/**
- * Adds a new {@link InlineAction} to this response representing an action UI.
- *
- * @return This builder.
- */
- @NonNull
- public Builder addInlineAction(@NonNull InlineAction inlineAction) {
- throwIfDestroyed();
- throwIfAuthenticationCalled();
- if (mInlineActions == null) {
- mInlineActions = new ArrayList<>();
- }
- mInlineActions.add(inlineAction);
- return this;
- }
-
- /**
* Builds a new {@link FillResponse} instance.
*
* @throws IllegalStateException if any of the following conditions occur:
@@ -788,9 +763,6 @@
builder.append(", mCancelIds=").append(mCancelIds.length);
}
builder.append(", mSupportInlinePresentations=").append(mSupportsInlineSuggestions);
- if (mInlineActions != null) {
- builder.append(", mInlineActions=" + mInlineActions);
- }
return builder.append("]").toString();
}
@@ -820,7 +792,6 @@
parcel.writeParcelableArray(mFieldClassificationIds, flags);
parcel.writeInt(mFlags);
parcel.writeIntArray(mCancelIds);
- parcel.writeTypedList(mInlineActions, flags);
parcel.writeInt(mRequestId);
}
@@ -878,14 +849,6 @@
final int[] cancelIds = parcel.createIntArray();
builder.setPresentationCancelIds(cancelIds);
- final List<InlineAction> inlineActions = parcel.createTypedArrayList(
- InlineAction.CREATOR);
- if (inlineActions != null) {
- for (InlineAction inlineAction : inlineActions) {
- builder.addInlineAction(inlineAction);
- }
- }
-
final FillResponse response = builder.build();
response.setRequestId(parcel.readInt());
diff --git a/core/java/android/service/autofill/InlineAction.aidl b/core/java/android/service/autofill/InlineAction.aidl
deleted file mode 100644
index 7f85118..0000000
--- a/core/java/android/service/autofill/InlineAction.aidl
+++ /dev/null
@@ -1,19 +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.service.autofill;
-
-parcelable InlineAction;
diff --git a/core/java/android/service/autofill/InlineAction.java b/core/java/android/service/autofill/InlineAction.java
deleted file mode 100644
index 17c4b33..0000000
--- a/core/java/android/service/autofill/InlineAction.java
+++ /dev/null
@@ -1,205 +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.service.autofill;
-
-import android.annotation.NonNull;
-import android.content.IntentSender;
-import android.os.Parcelable;
-
-import com.android.internal.util.DataClass;
-
-/**
- * Represents an inline action as part of the autofill/augmented autofill response.
- *
- * <p> It includes both the action intent and the UI presentation. For example, the UI can be
- * associated with an intent which can open an activity for the user to manage the Autofill provider
- * settings.
- */
-@DataClass(
- genToString = true,
- genHiddenConstDefs = true,
- genEqualsHashCode = true)
-public final class InlineAction implements Parcelable {
-
- /**
- * Representation of the inline action.
- */
- private final @NonNull InlinePresentation mInlinePresentation;
-
- /**
- * The associated intent which will be triggered when the action is selected. It will only be
- * called by the OS.
- */
- private final @NonNull IntentSender mAction;
-
-
-
- // Code below generated by codegen v1.0.15.
- //
- // DO NOT MODIFY!
- // CHECKSTYLE:OFF Generated code
- //
- // To regenerate run:
- // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/autofill/InlineAction.java
- //
- // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
- // Settings > Editor > Code Style > Formatter Control
- //@formatter:off
-
-
- /**
- * Creates a new InlineAction.
- *
- * @param inlinePresentation
- * Representation of the inline action.
- * @param action
- * The associated intent which will be triggered when the action is selected. It will only be
- * invoked by the OS.
- */
- @DataClass.Generated.Member
- public InlineAction(
- @NonNull InlinePresentation inlinePresentation,
- @NonNull IntentSender action) {
- this.mInlinePresentation = inlinePresentation;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mInlinePresentation);
- this.mAction = action;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mAction);
-
- // onConstructed(); // You can define this method to get a callback
- }
-
- /**
- * Representation of the inline action.
- */
- @DataClass.Generated.Member
- public @NonNull InlinePresentation getInlinePresentation() {
- return mInlinePresentation;
- }
-
- /**
- * The associated intent which will be triggered when the action is selected. It will only be
- * invoked by the OS.
- */
- @DataClass.Generated.Member
- public @NonNull IntentSender getAction() {
- return mAction;
- }
-
- @Override
- @DataClass.Generated.Member
- public String toString() {
- // You can override field toString logic by defining methods like:
- // String fieldNameToString() { ... }
-
- return "InlineAction { " +
- "inlinePresentation = " + mInlinePresentation + ", " +
- "action = " + mAction +
- " }";
- }
-
- @Override
- @DataClass.Generated.Member
- public boolean equals(@android.annotation.Nullable Object o) {
- // You can override field equality logic by defining either of the methods like:
- // boolean fieldNameEquals(InlineAction other) { ... }
- // boolean fieldNameEquals(FieldType otherValue) { ... }
-
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- @SuppressWarnings("unchecked")
- InlineAction that = (InlineAction) o;
- //noinspection PointlessBooleanExpression
- return true
- && java.util.Objects.equals(mInlinePresentation, that.mInlinePresentation)
- && java.util.Objects.equals(mAction, that.mAction);
- }
-
- @Override
- @DataClass.Generated.Member
- public int hashCode() {
- // You can override field hashCode logic by defining methods like:
- // int fieldNameHashCode() { ... }
-
- int _hash = 1;
- _hash = 31 * _hash + java.util.Objects.hashCode(mInlinePresentation);
- _hash = 31 * _hash + java.util.Objects.hashCode(mAction);
- return _hash;
- }
-
- @Override
- @DataClass.Generated.Member
- public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
- // You can override field parcelling by defining methods like:
- // void parcelFieldName(Parcel dest, int flags) { ... }
-
- dest.writeTypedObject(mInlinePresentation, flags);
- dest.writeTypedObject(mAction, flags);
- }
-
- @Override
- @DataClass.Generated.Member
- public int describeContents() { return 0; }
-
- /** @hide */
- @SuppressWarnings({"unchecked", "RedundantCast"})
- @DataClass.Generated.Member
- /* package-private */ InlineAction(@NonNull android.os.Parcel in) {
- // You can override field unparcelling by defining methods like:
- // static FieldType unparcelFieldName(Parcel in) { ... }
-
- InlinePresentation inlinePresentation = (InlinePresentation) in.readTypedObject(InlinePresentation.CREATOR);
- IntentSender action = (IntentSender) in.readTypedObject(IntentSender.CREATOR);
-
- this.mInlinePresentation = inlinePresentation;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mInlinePresentation);
- this.mAction = action;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mAction);
-
- // onConstructed(); // You can define this method to get a callback
- }
-
- @DataClass.Generated.Member
- public static final @NonNull Parcelable.Creator<InlineAction> CREATOR
- = new Parcelable.Creator<InlineAction>() {
- @Override
- public InlineAction[] newArray(int size) {
- return new InlineAction[size];
- }
-
- @Override
- public InlineAction createFromParcel(@NonNull android.os.Parcel in) {
- return new InlineAction(in);
- }
- };
-
- @DataClass.Generated(
- time = 1583798182424L,
- codegenVersion = "1.0.15",
- sourceFile = "frameworks/base/core/java/android/service/autofill/InlineAction.java",
- inputSignatures = "private final @android.annotation.NonNull android.service.autofill.InlinePresentation mInlinePresentation\nprivate final @android.annotation.NonNull android.content.IntentSender mAction\nclass InlineAction extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genEqualsHashCode=true)")
- @Deprecated
- private void __metadata() {}
-
-
- //@formatter:on
- // End of generated code
-
-}
diff --git a/core/java/android/service/autofill/InlineSuggestionRenderService.java b/core/java/android/service/autofill/InlineSuggestionRenderService.java
index f0a72c5..7fbc309 100644
--- a/core/java/android/service/autofill/InlineSuggestionRenderService.java
+++ b/core/java/android/service/autofill/InlineSuggestionRenderService.java
@@ -97,6 +97,9 @@
host.setView(suggestionRoot, lp);
suggestionRoot.setOnClickListener((v) -> {
try {
+ if (suggestionView.hasOnClickListeners()) {
+ suggestionView.callOnClick();
+ }
callback.onClick();
} catch (RemoteException e) {
Log.w(TAG, "RemoteException calling onClick()");
@@ -105,6 +108,9 @@
suggestionRoot.setOnLongClickListener((v) -> {
try {
+ if (suggestionView.hasOnLongClickListeners()) {
+ suggestionView.performLongClick();
+ }
callback.onLongClick();
} catch (RemoteException e) {
Log.w(TAG, "RemoteException calling onLongClick()");
diff --git a/core/java/android/service/autofill/InlineSuggestionRoot.java b/core/java/android/service/autofill/InlineSuggestionRoot.java
index bdcc253..6c9d36b 100644
--- a/core/java/android/service/autofill/InlineSuggestionRoot.java
+++ b/core/java/android/service/autofill/InlineSuggestionRoot.java
@@ -52,6 +52,11 @@
}
@Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ return true;
+ }
+
+ @Override
@SuppressLint("ClickableViewAccessibility")
public boolean onTouchEvent(@NonNull MotionEvent event) {
switch (event.getActionMasked()) {
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index 5b08ae20..1efa3dd 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -40,7 +40,6 @@
import android.os.SystemClock;
import android.service.autofill.Dataset;
import android.service.autofill.FillEventHistory;
-import android.service.autofill.InlineAction;
import android.service.autofill.augmented.PresentationParams.SystemPopupPresentationParams;
import android.util.Log;
import android.util.Pair;
@@ -559,10 +558,9 @@
}
}
- void reportResult(@Nullable List<Dataset> inlineSuggestionsData,
- @Nullable List<InlineAction> inlineActions) {
+ void reportResult(@Nullable List<Dataset> inlineSuggestionsData) {
try {
- mCallback.onSuccess(inlineSuggestionsData, inlineActions);
+ mCallback.onSuccess(inlineSuggestionsData);
} catch (RemoteException e) {
Log.e(TAG, "Error calling back with the inline suggestions data: " + e);
}
diff --git a/core/java/android/service/autofill/augmented/FillCallback.java b/core/java/android/service/autofill/augmented/FillCallback.java
index 6b4e118..526a749 100644
--- a/core/java/android/service/autofill/augmented/FillCallback.java
+++ b/core/java/android/service/autofill/augmented/FillCallback.java
@@ -55,14 +55,14 @@
if (response == null) {
mProxy.logEvent(AutofillProxy.REPORT_EVENT_NO_RESPONSE);
- mProxy.reportResult(/* inlineSuggestionsData */ null, /* inlineActions */null);
+ mProxy.reportResult(/* inlineSuggestionsData */ null);
return;
}
List<Dataset> inlineSuggestions = response.getInlineSuggestions();
if (inlineSuggestions != null && !inlineSuggestions.isEmpty()) {
mProxy.logEvent(AutofillProxy.REPORT_EVENT_INLINE_RESPONSE);
- mProxy.reportResult(inlineSuggestions, response.getInlineActions());
+ mProxy.reportResult(inlineSuggestions);
return;
}
diff --git a/core/java/android/service/autofill/augmented/FillResponse.java b/core/java/android/service/autofill/augmented/FillResponse.java
index f564b3b..f72eb78 100644
--- a/core/java/android/service/autofill/augmented/FillResponse.java
+++ b/core/java/android/service/autofill/augmented/FillResponse.java
@@ -21,7 +21,6 @@
import android.annotation.TestApi;
import android.os.Bundle;
import android.service.autofill.Dataset;
-import android.service.autofill.InlineAction;
import com.android.internal.util.DataClass;
@@ -53,12 +52,6 @@
private @Nullable List<Dataset> mInlineSuggestions;
/**
- * Defaults to null if no inline actions are provided.
- */
- @DataClass.PluralOf("inlineAction")
- private @Nullable List<InlineAction> mInlineActions;
-
- /**
* The client state that {@link AugmentedAutofillService} implementation can put anything in to
* identify the request and the response when calling
* {@link AugmentedAutofillService#getFillEventHistory()}.
@@ -73,10 +66,6 @@
return null;
}
- private static List<InlineAction> defaultInlineActions() {
- return null;
- }
-
private static Bundle defaultClientState() {
return null;
}
@@ -85,7 +74,6 @@
/** @hide */
abstract static class BaseBuilder {
abstract FillResponse.Builder addInlineSuggestion(@NonNull Dataset value);
- abstract FillResponse.Builder addInlineAction(@NonNull InlineAction value);
}
@@ -107,11 +95,9 @@
/* package-private */ FillResponse(
@Nullable FillWindow fillWindow,
@Nullable List<Dataset> inlineSuggestions,
- @Nullable List<InlineAction> inlineActions,
@Nullable Bundle clientState) {
this.mFillWindow = fillWindow;
this.mInlineSuggestions = inlineSuggestions;
- this.mInlineActions = inlineActions;
this.mClientState = clientState;
// onConstructed(); // You can define this method to get a callback
@@ -139,16 +125,6 @@
}
/**
- * Defaults to null if no inline actions are provided.
- *
- * @hide
- */
- @DataClass.Generated.Member
- public @Nullable List<InlineAction> getInlineActions() {
- return mInlineActions;
- }
-
- /**
* The client state that {@link AugmentedAutofillService} implementation can put anything in to
* identify the request and the response when calling
* {@link AugmentedAutofillService#getFillEventHistory()}.
@@ -169,7 +145,6 @@
private @Nullable FillWindow mFillWindow;
private @Nullable List<Dataset> mInlineSuggestions;
- private @Nullable List<InlineAction> mInlineActions;
private @Nullable Bundle mClientState;
private long mBuilderFieldsSet = 0L;
@@ -210,26 +185,6 @@
}
/**
- * Defaults to null if no inline actions are provided.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setInlineActions(@NonNull List<InlineAction> value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x4;
- mInlineActions = value;
- return this;
- }
-
- /** @see #setInlineActions */
- @DataClass.Generated.Member
- @Override
- @NonNull FillResponse.Builder addInlineAction(@NonNull InlineAction value) {
- if (mInlineActions == null) setInlineActions(new ArrayList<>());
- mInlineActions.add(value);
- return this;
- }
-
- /**
* The client state that {@link AugmentedAutofillService} implementation can put anything in to
* identify the request and the response when calling
* {@link AugmentedAutofillService#getFillEventHistory()}.
@@ -237,7 +192,7 @@
@DataClass.Generated.Member
public @NonNull Builder setClientState(@NonNull Bundle value) {
checkNotUsed();
- mBuilderFieldsSet |= 0x8;
+ mBuilderFieldsSet |= 0x4;
mClientState = value;
return this;
}
@@ -245,7 +200,7 @@
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull FillResponse build() {
checkNotUsed();
- mBuilderFieldsSet |= 0x10; // Mark builder used
+ mBuilderFieldsSet |= 0x8; // Mark builder used
if ((mBuilderFieldsSet & 0x1) == 0) {
mFillWindow = defaultFillWindow();
@@ -254,21 +209,17 @@
mInlineSuggestions = defaultInlineSuggestions();
}
if ((mBuilderFieldsSet & 0x4) == 0) {
- mInlineActions = defaultInlineActions();
- }
- if ((mBuilderFieldsSet & 0x8) == 0) {
mClientState = defaultClientState();
}
FillResponse o = new FillResponse(
mFillWindow,
mInlineSuggestions,
- mInlineActions,
mClientState);
return o;
}
private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x10) != 0) {
+ if ((mBuilderFieldsSet & 0x8) != 0) {
throw new IllegalStateException(
"This Builder should not be reused. Use a new Builder instance instead");
}
@@ -276,10 +227,10 @@
}
@DataClass.Generated(
- time = 1583793032373L,
+ time = 1584480900526L,
codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/service/autofill/augmented/FillResponse.java",
- inputSignatures = "private @android.annotation.Nullable android.service.autofill.augmented.FillWindow mFillWindow\nprivate @com.android.internal.util.DataClass.PluralOf(\"inlineSuggestion\") @android.annotation.Nullable java.util.List<android.service.autofill.Dataset> mInlineSuggestions\nprivate @com.android.internal.util.DataClass.PluralOf(\"inlineAction\") @android.annotation.Nullable java.util.List<android.service.autofill.InlineAction> mInlineActions\nprivate @android.annotation.Nullable android.os.Bundle mClientState\nprivate static android.service.autofill.augmented.FillWindow defaultFillWindow()\nprivate static java.util.List<android.service.autofill.Dataset> defaultInlineSuggestions()\nprivate static java.util.List<android.service.autofill.InlineAction> defaultInlineActions()\nprivate static android.os.Bundle defaultClientState()\nclass FillResponse extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genHiddenGetters=true)\nabstract android.service.autofill.augmented.FillResponse.Builder addInlineSuggestion(android.service.autofill.Dataset)\nabstract android.service.autofill.augmented.FillResponse.Builder addInlineAction(android.service.autofill.InlineAction)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "private @android.annotation.Nullable android.service.autofill.augmented.FillWindow mFillWindow\nprivate @com.android.internal.util.DataClass.PluralOf(\"inlineSuggestion\") @android.annotation.Nullable java.util.List<android.service.autofill.Dataset> mInlineSuggestions\nprivate @android.annotation.Nullable android.os.Bundle mClientState\nprivate static android.service.autofill.augmented.FillWindow defaultFillWindow()\nprivate static java.util.List<android.service.autofill.Dataset> defaultInlineSuggestions()\nprivate static android.os.Bundle defaultClientState()\nclass FillResponse extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genBuilder=true, genHiddenGetters=true)\nabstract android.service.autofill.augmented.FillResponse.Builder addInlineSuggestion(android.service.autofill.Dataset)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/service/autofill/augmented/IFillCallback.aidl b/core/java/android/service/autofill/augmented/IFillCallback.aidl
index 545dab2..24af1e5 100644
--- a/core/java/android/service/autofill/augmented/IFillCallback.aidl
+++ b/core/java/android/service/autofill/augmented/IFillCallback.aidl
@@ -20,7 +20,6 @@
import android.os.ICancellationSignal;
import android.service.autofill.Dataset;
-import android.service.autofill.InlineAction;
import java.util.List;
@@ -31,8 +30,7 @@
*/
interface IFillCallback {
void onCancellable(in ICancellationSignal cancellation);
- void onSuccess(in @nullable List<Dataset> inlineSuggestionsData,
- in @nullable List<InlineAction> inlineActions);
+ void onSuccess(in @nullable List<Dataset> inlineSuggestionsData);
boolean isCompleted();
void cancel();
}
diff --git a/core/java/android/service/dataloader/DataLoaderService.java b/core/java/android/service/dataloader/DataLoaderService.java
index d4db79e..0170726 100644
--- a/core/java/android/service/dataloader/DataLoaderService.java
+++ b/core/java/android/service/dataloader/DataLoaderService.java
@@ -102,21 +102,18 @@
}
private class DataLoaderBinderService extends IDataLoader.Stub {
- private int mId;
-
@Override
public void create(int id, @NonNull DataLoaderParamsParcel params,
@NonNull FileSystemControlParcel control,
@NonNull IDataLoaderStatusListener listener)
throws RuntimeException {
- mId = id;
try {
if (!nativeCreateDataLoader(id, control, params, listener)) {
- Slog.e(TAG, "Failed to create native loader for " + mId);
+ Slog.e(TAG, "Failed to create native loader for " + id);
}
} catch (Exception ex) {
- Slog.e(TAG, "Failed to create native loader for " + mId, ex);
- destroy();
+ Slog.e(TAG, "Failed to create native loader for " + id, ex);
+ destroy(id);
throw new RuntimeException(ex);
} finally {
// Closing FDs.
@@ -150,30 +147,31 @@
}
@Override
- public void start() {
- if (!nativeStartDataLoader(mId)) {
- Slog.e(TAG, "Failed to start loader: " + mId);
+ public void start(int id) {
+ if (!nativeStartDataLoader(id)) {
+ Slog.e(TAG, "Failed to start loader: " + id);
}
}
@Override
- public void stop() {
- if (!nativeStopDataLoader(mId)) {
- Slog.w(TAG, "Failed to stop loader: " + mId);
+ public void stop(int id) {
+ if (!nativeStopDataLoader(id)) {
+ Slog.w(TAG, "Failed to stop loader: " + id);
}
}
@Override
- public void destroy() {
- if (!nativeDestroyDataLoader(mId)) {
- Slog.w(TAG, "Failed to destroy loader: " + mId);
+ public void destroy(int id) {
+ if (!nativeDestroyDataLoader(id)) {
+ Slog.w(TAG, "Failed to destroy loader: " + id);
}
}
@Override
- public void prepareImage(InstallationFileParcel[] addedFiles, String[] removedFiles) {
- if (!nativePrepareImage(mId, addedFiles, removedFiles)) {
- Slog.w(TAG, "Failed to prepare image for data loader: " + mId);
+ public void prepareImage(int id, InstallationFileParcel[] addedFiles,
+ String[] removedFiles) {
+ if (!nativePrepareImage(id, addedFiles, removedFiles)) {
+ Slog.w(TAG, "Failed to prepare image for data loader: " + id);
}
}
}
diff --git a/core/java/android/service/quickaccesswallet/WalletServiceEvent.java b/core/java/android/service/quickaccesswallet/WalletServiceEvent.java
index fb524be..5ee92da 100644
--- a/core/java/android/service/quickaccesswallet/WalletServiceEvent.java
+++ b/core/java/android/service/quickaccesswallet/WalletServiceEvent.java
@@ -40,10 +40,16 @@
public static final int TYPE_NFC_PAYMENT_STARTED = 1;
/**
+ * Indicates that the wallet cards have changed and should be refreshed.
+ * @hide
+ */
+ public static final int TYPE_WALLET_CARDS_UPDATED = 2;
+
+ /**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef({TYPE_NFC_PAYMENT_STARTED})
+ @IntDef({TYPE_NFC_PAYMENT_STARTED, TYPE_WALLET_CARDS_UPDATED})
public @interface EventType {
}
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index d273500..28db270 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -176,7 +176,6 @@
* @hide
*/
@RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
- @SystemApi
public static final int LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH = 0x00000200;
/**
diff --git a/core/java/android/telephony/SubscriptionPlan.java b/core/java/android/telephony/SubscriptionPlan.java
index ff2f4ad..901957f 100644
--- a/core/java/android/telephony/SubscriptionPlan.java
+++ b/core/java/android/telephony/SubscriptionPlan.java
@@ -91,10 +91,11 @@
private long dataUsageBytes = BYTES_UNKNOWN;
private long dataUsageTime = TIME_UNKNOWN;
private @NetworkType int[] networkTypes;
- private long networkTypesBitMask;
private SubscriptionPlan(RecurrenceRule cycleRule) {
this.cycleRule = Preconditions.checkNotNull(cycleRule);
+ this.networkTypes = Arrays.copyOf(TelephonyManager.getAllNetworkTypes(),
+ TelephonyManager.getAllNetworkTypes().length);
}
private SubscriptionPlan(Parcel source) {
@@ -221,10 +222,10 @@
/**
* Return an array containing all {@link NetworkType}s this SubscriptionPlan applies to.
- * A null value means this SubscriptionPlan applies to all network types.
+ * @see TelephonyManager for network types values
*/
- public @Nullable @NetworkType int[] getNetworkTypes() {
- return networkTypes;
+ public @NonNull @NetworkType int[] getNetworkTypes() {
+ return Arrays.copyOf(networkTypes, networkTypes.length);
}
/**
@@ -361,14 +362,14 @@
}
/**
- * Set the network types this SubscriptionPlan applies to.
+ * Set the network types this SubscriptionPlan applies to. By default the plan will apply
+ * to all network types. An empty array means this plan applies to no network types.
*
- * @param networkTypes a set of all {@link NetworkType}s that apply to this plan.
- * A null value means the plan applies to all network types,
- * and an empty array means the plan applies to no network types.
+ * @param networkTypes an array of all {@link NetworkType}s that apply to this plan.
+ * @see TelephonyManager for network type values
*/
- public @NonNull Builder setNetworkTypes(@Nullable @NetworkType int[] networkTypes) {
- plan.networkTypes = networkTypes;
+ public @NonNull Builder setNetworkTypes(@NonNull @NetworkType int[] networkTypes) {
+ plan.networkTypes = Arrays.copyOf(networkTypes, networkTypes.length);
return this;
}
}
diff --git a/core/java/android/text/style/ReplacementSpan.java b/core/java/android/text/style/ReplacementSpan.java
index 0553232..9430fd3 100644
--- a/core/java/android/text/style/ReplacementSpan.java
+++ b/core/java/android/text/style/ReplacementSpan.java
@@ -63,7 +63,7 @@
int top, int y, int bottom, @NonNull Paint paint);
/**
- * Gets a brief description of this ImageSpan for use in accessibility support.
+ * Gets a brief description of this ReplacementSpan for use in accessibility support.
*
* @return The content description.
*/
@@ -73,7 +73,7 @@
}
/**
- * Sets the specific content description into ImageSpan.
+ * Sets the specific content description into ReplacementSpan.
* ReplacementSpans are shared with accessibility services,
* but only the content description is available from them.
*
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index cfbe393..4dafc0d 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -67,9 +67,9 @@
DEFAULT_FLAGS.put("settings_controller_loading_enhancement", "false");
DEFAULT_FLAGS.put("settings_conditionals", "false");
DEFAULT_FLAGS.put(NOTIF_CONVO_BYPASS_SHORTCUT_REQ, "true");
- // Disabled by default until b/148278926 is resolved. This flags guards a feature
- // introduced in R and will be removed in the next release (b/148367230).
- DEFAULT_FLAGS.put(SETTINGS_DO_NOT_RESTORE_PRESERVED, "false");
+ // This flags guards a feature introduced in R and will be removed in the next release
+ // (b/148367230).
+ DEFAULT_FLAGS.put(SETTINGS_DO_NOT_RESTORE_PRESERVED, "true");
DEFAULT_FLAGS.put("settings_tether_all_in_one", "false");
DEFAULT_FLAGS.put(SETTINGS_SCHEDULES_FLAG, "false");
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
index 79eb9f6..2437af2 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -213,15 +213,24 @@
verityDigest, apk.length(), signatureInfo);
}
- if (contentDigests.containsKey(CONTENT_DIGEST_CHUNKED_SHA512)) {
- result.digest = contentDigests.get(CONTENT_DIGEST_CHUNKED_SHA512);
- } else if (contentDigests.containsKey(CONTENT_DIGEST_CHUNKED_SHA256)) {
- result.digest = contentDigests.get(CONTENT_DIGEST_CHUNKED_SHA256);
- }
+ result.digest = pickBestV3DigestForV4(contentDigests);
return result;
}
+ // Keep in sync with pickBestV3DigestForV4 in apksigner.V3SchemeVerifier.
+ private static byte[] pickBestV3DigestForV4(Map<Integer, byte[]> contentDigests) {
+ final int[] orderedContentDigestTypes =
+ {CONTENT_DIGEST_CHUNKED_SHA512, CONTENT_DIGEST_VERITY_CHUNKED_SHA256,
+ CONTENT_DIGEST_CHUNKED_SHA256};
+ for (int contentDigestType : orderedContentDigestTypes) {
+ if (contentDigests.containsKey(contentDigestType)) {
+ return contentDigests.get(contentDigestType);
+ }
+ }
+ return null;
+ }
+
private static VerifiedSigner verifySigner(
ByteBuffer signerBlock,
Map<Integer, byte[]> contentDigests,
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 0dcb9cc..dffcafe 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1307,6 +1307,15 @@
}
/**
+ * Returns true if the display is in active state such as {@link #STATE_ON}
+ * or {@link #STATE_VR}.
+ * @hide
+ */
+ public static boolean isActiveState(int state) {
+ return state == STATE_ON || state == STATE_VR;
+ }
+
+ /**
* A mode supported by a given display.
*
* @see Display#getSupportedModes()
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index baee412..d2e6036 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -200,6 +200,7 @@
}
setInsetsAndAlpha(shown ? mShownInsets : mHiddenInsets, 1f /* alpha */, 1f /* fraction */);
mFinished = true;
+ mListener.onFinished(this);
mShownOnFinish = shown;
}
@@ -216,11 +217,17 @@
return;
}
mCancelled = true;
- mListener.onCancelled();
+ mListener.onCancelled(this);
releaseLeashes();
}
+ @Override
+ public boolean isFinished() {
+ return mFinished;
+ }
+
+ @Override
public boolean isCancelled() {
return mCancelled;
}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 123b9db..96f7340 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -213,7 +213,11 @@
}
@Override
- public void onCancelled() {
+ public void onFinished(WindowInsetsAnimationController controller) {
+ }
+
+ @Override
+ public void onCancelled(WindowInsetsAnimationController controller) {
// Animator can be null when it is cancelled before onReady() completes.
if (mAnimator != null) {
mAnimator.cancel();
@@ -583,7 +587,7 @@
boolean fromIme, long durationMs, @Nullable Interpolator interpolator,
@AnimationType int animationType) {
if (!checkDisplayFramesForControlling()) {
- listener.onCancelled();
+ listener.onCancelled(null);
return;
}
controlAnimationUnchecked(types, cancellationSignal, listener, mFrame, fromIme, durationMs,
@@ -608,7 +612,7 @@
boolean useInsetsAnimationThread) {
if (types == 0) {
// nothing to animate.
- listener.onCancelled();
+ listener.onCancelled(null);
return;
}
cancelExistingControllers(types);
@@ -641,7 +645,7 @@
}
if (typesReady == 0) {
- listener.onCancelled();
+ listener.onCancelled(null);
return;
}
@@ -756,7 +760,7 @@
private void abortPendingImeControlRequest() {
if (mPendingImeControlRequest != null) {
- mPendingImeControlRequest.listener.onCancelled();
+ mPendingImeControlRequest.listener.onCancelled(null);
mPendingImeControlRequest = null;
mHandler.removeCallbacks(mPendingControlTimeout);
}
diff --git a/core/java/android/view/PendingInsetsController.java b/core/java/android/view/PendingInsetsController.java
index e8d9bb5..229ee03 100644
--- a/core/java/android/view/PendingInsetsController.java
+++ b/core/java/android/view/PendingInsetsController.java
@@ -172,7 +172,7 @@
mReplayedInsetsController.controlWindowInsetsAnimation(types, durationMillis,
interpolator, cancellationSignal, listener);
} else {
- listener.onCancelled();
+ listener.onCancelled(null);
}
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 25f5609..c87808b 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1960,7 +1960,7 @@
* @hide
*/
public static ScreenshotGraphicBuffer captureLayersExcluding(SurfaceControl layer,
- Rect sourceCrop, float frameScale, SurfaceControl[] exclude) {
+ Rect sourceCrop, float frameScale, int format, SurfaceControl[] exclude) {
final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
long[] nativeExcludeObjects = new long[exclude.length];
for (int i = 0; i < exclude.length; i++) {
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 41a3847..cd22ad6 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -52,7 +52,7 @@
* a SurfaceView by calling {@link SurfaceView#setChildSurfacePackage}.
*/
public static final class SurfacePackage implements Parcelable {
- private final SurfaceControl mSurfaceControl;
+ private SurfaceControl mSurfaceControl;
private final IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection;
SurfacePackage(SurfaceControl sc, IAccessibilityEmbeddedConnection connection) {
@@ -97,6 +97,19 @@
out.writeStrongBinder(mAccessibilityEmbeddedConnection.asBinder());
}
+ /**
+ * Release the {@link SurfaceControl} associated with this package.
+ * It's not necessary to call this if you pass the package to
+ * {@link SurfaceView#setChildSurfacePackage} as {@link SurfaceView} will
+ * take ownership in that case.
+ */
+ public void release() {
+ if (mSurfaceControl != null) {
+ mSurfaceControl.release();
+ }
+ mSurfaceControl = null;
+ }
+
public static final @NonNull Creator<SurfacePackage> CREATOR
= new Creator<SurfacePackage>() {
public SurfacePackage createFromParcel(Parcel in) {
@@ -220,7 +233,7 @@
* and render the object unusable.
*/
public void release() {
- mViewRoot.dispatchDetachedFromWindow();
+ mViewRoot.die(false /* immediate */);
mSurfaceControl.release();
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 1f7c3504..3e1e393 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -496,8 +496,17 @@
updateSurface();
releaseSurfaces();
- mHaveFrame = false;
+ // We don't release this as part of releaseSurfaces as
+ // that is also called on transient visibility changes. We can't
+ // recreate this Surface, so only release it when we are fully
+ // detached.
+ if (mSurfacePackage != null) {
+ mSurfacePackage.release();
+ mSurfacePackage = null;
+ }
+
+ mHaveFrame = false;
super.onDetachedFromWindow();
}
@@ -1546,7 +1555,9 @@
* Display the view-hierarchy embedded within a {@link SurfaceControlViewHost.SurfacePackage}
* within this SurfaceView. If this SurfaceView is above it's host Surface (see
* {@link #setZOrderOnTop} then the embedded Surface hierarchy will be able to receive
- * input.
+ * input. This will take ownership of the SurfaceControl contained inside the SurfacePackage
+ * and free the caller of the obligation to call
+ * {@link SurfaceControlViewHost.SurfacePackage#release}.
*
* @param p The SurfacePackage to embed.
*/
@@ -1556,6 +1567,7 @@
mSurfacePackage.getSurfaceControl() : null;
if (mSurfaceControl != null && lastSc != null) {
mTmpTransaction.reparent(lastSc, null).apply();
+ mSurfacePackage.release();
} else if (mSurfaceControl != null) {
reparentSurfacePackage(mTmpTransaction, p);
mTmpTransaction.apply();
diff --git a/core/java/android/view/WindowContainerTransaction.java b/core/java/android/view/WindowContainerTransaction.java
index 9c16e13..56b4951 100644
--- a/core/java/android/view/WindowContainerTransaction.java
+++ b/core/java/android/view/WindowContainerTransaction.java
@@ -168,6 +168,18 @@
}
/**
+ * Sets whether a container or its children should be hidden. When {@code false}, the existing
+ * visibility of the container applies, but when {@code true} the container will be forced
+ * to be hidden.
+ */
+ public WindowContainerTransaction setHidden(IWindowContainer container, boolean hidden) {
+ Change chg = getOrCreateChange(container.asBinder());
+ chg.mHidden = hidden;
+ chg.mChangeMask |= Change.CHANGE_HIDDEN;
+ return this;
+ }
+
+ /**
* Set the smallestScreenWidth of a container.
*/
public WindowContainerTransaction setSmallestScreenWidthDp(IWindowContainer container,
@@ -250,9 +262,11 @@
public static final int CHANGE_FOCUSABLE = 1;
public static final int CHANGE_BOUNDS_TRANSACTION = 1 << 1;
public static final int CHANGE_PIP_CALLBACK = 1 << 2;
+ public static final int CHANGE_HIDDEN = 1 << 3;
private final Configuration mConfiguration = new Configuration();
private boolean mFocusable = true;
+ private boolean mHidden = false;
private int mChangeMask = 0;
private @ActivityInfo.Config int mConfigSetMask = 0;
private @WindowConfiguration.WindowConfig int mWindowSetMask = 0;
@@ -268,6 +282,7 @@
protected Change(Parcel in) {
mConfiguration.readFromParcel(in);
mFocusable = in.readBoolean();
+ mHidden = in.readBoolean();
mChangeMask = in.readInt();
mConfigSetMask = in.readInt();
mWindowSetMask = in.readInt();
@@ -296,7 +311,7 @@
return mConfiguration;
}
- /** Gets the requested focusable value */
+ /** Gets the requested focusable state */
public boolean getFocusable() {
if ((mChangeMask & CHANGE_FOCUSABLE) == 0) {
throw new RuntimeException("Focusable not set. check CHANGE_FOCUSABLE first");
@@ -304,6 +319,14 @@
return mFocusable;
}
+ /** Gets the requested hidden state */
+ public boolean getHidden() {
+ if ((mChangeMask & CHANGE_HIDDEN) == 0) {
+ throw new RuntimeException("Hidden not set. check CHANGE_HIDDEN first");
+ }
+ return mHidden;
+ }
+
public int getChangeMask() {
return mChangeMask;
}
@@ -369,6 +392,7 @@
public void writeToParcel(Parcel dest, int flags) {
mConfiguration.writeToParcel(dest, flags);
dest.writeBoolean(mFocusable);
+ dest.writeBoolean(mHidden);
dest.writeInt(mChangeMask);
dest.writeInt(mConfigSetMask);
dest.writeInt(mWindowSetMask);
diff --git a/core/java/android/view/WindowInsetsAnimationControlListener.java b/core/java/android/view/WindowInsetsAnimationControlListener.java
index faaf920..b61fa36 100644
--- a/core/java/android/view/WindowInsetsAnimationControlListener.java
+++ b/core/java/android/view/WindowInsetsAnimationControlListener.java
@@ -17,21 +17,31 @@
package android.view;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.view.WindowInsets.Type.InsetsType;
import android.view.inputmethod.EditorInfo;
/**
- * Interface that informs the client about {@link WindowInsetsAnimationController} state changes.
+ * Listener that encapsulates a request to
+ * {@link WindowInsetsController#controlWindowInsetsAnimation}.
+ *
+ * <p>
+ * Insets can be controlled with the supplied {@link WindowInsetsAnimationController} from
+ * {@link #onReady} until either {@link #onFinished} or {@link #onCancelled}.
+ *
+ * <p>
+ * Once the control over insets is finished or cancelled, it will not be regained until a new
+ * request to {@link WindowInsetsController#controlWindowInsetsAnimation} is made.
+ *
+ * <p>
+ * The request to control insets can fail immediately. In that case {@link #onCancelled} will be
+ * invoked without a preceding {@link #onReady}.
+ *
+ * @see WindowInsetsController#controlWindowInsetsAnimation
*/
public interface WindowInsetsAnimationControlListener {
/**
- * @hide
- */
- default void onPrepare(int types) {
- }
-
- /**
* Called when the animation is ready to be controlled. This may be delayed when the IME needs
* to redraw because of an {@link EditorInfo} change, or when the window is starting up.
*
@@ -41,14 +51,40 @@
* {@link WindowInsetsController#controlWindowInsetsAnimation} in case the window
* wasn't able to gain the controls because it wasn't the IME target or not
* currently the window that's controlling the system bars.
+ * @see WindowInsetsAnimationController#isReady
*/
void onReady(@NonNull WindowInsetsAnimationController controller, @InsetsType int types);
/**
- * Called when the window no longer has control over the requested types. If it loses control
- * over one type, the whole control will be cancelled. If none of the requested types were
- * available when requesting the control, the animation control will be cancelled immediately
- * without {@link #onReady} being called.
+ * Called when the request for control over the insets has
+ * {@link WindowInsetsAnimationController#finish finished}.
+ *
+ * Once this callback is invoked, the supplied {@link WindowInsetsAnimationController}
+ * is no longer {@link WindowInsetsAnimationController#isReady() ready}.
+ *
+ * Control will not be regained until a new request
+ * to {@link WindowInsetsController#controlWindowInsetsAnimation} is made.
+ *
+ * @param controller the controller which has finished.
+ * @see WindowInsetsAnimationController#isFinished
*/
- void onCancelled();
+ void onFinished(@NonNull WindowInsetsAnimationController controller);
+
+ /**
+ * Called when the request for control over the insets has been cancelled, either
+ * because the {@link android.os.CancellationSignal} associated with the
+ * {@link WindowInsetsController#controlWindowInsetsAnimation request} has been invoked, or
+ * the window has lost control over the insets (e.g. because it lost focus).
+ *
+ * Once this callback is invoked, the supplied {@link WindowInsetsAnimationController}
+ * is no longer {@link WindowInsetsAnimationController#isReady() ready}.
+ *
+ * Control will not be regained until a new request
+ * to {@link WindowInsetsController#controlWindowInsetsAnimation} is made.
+ *
+ * @param controller the controller which has been cancelled, or null if the request
+ * was cancelled before {@link #onReady} was invoked.
+ * @see WindowInsetsAnimationController#isCancelled
+ */
+ void onCancelled(@Nullable WindowInsetsAnimationController controller);
}
diff --git a/core/java/android/view/WindowInsetsAnimationController.java b/core/java/android/view/WindowInsetsAnimationController.java
index 2c7880b..c191a54 100644
--- a/core/java/android/view/WindowInsetsAnimationController.java
+++ b/core/java/android/view/WindowInsetsAnimationController.java
@@ -139,10 +139,43 @@
@FloatRange(from = 0f, to = 1f) float fraction);
/**
- * Finishes the animation, and leaves the windows shown or hidden. After invoking
- * {@link #finish(boolean)}, this instance is no longer valid.
+ * Finishes the animation, and leaves the windows shown or hidden.
+ * <p>
+ * After invoking {@link #finish(boolean)}, this instance is no longer {@link #isReady ready}.
+ *
* @param shown if {@code true}, the windows will be shown after finishing the
* animation. Otherwise they will be hidden.
*/
void finish(boolean shown);
+
+ /**
+ * Returns whether this instance is ready to be used to control window insets.
+ * <p>
+ * Instances are ready when passed in {@link WindowInsetsAnimationControlListener#onReady}
+ * and stop being ready when it is either {@link #isFinished() finished} or
+ * {@link #isCancelled() cancelled}.
+ *
+ * @return {@code true} if the instance is ready, {@code false} otherwise.
+ */
+ default boolean isReady() {
+ return !isFinished() && !isCancelled();
+ }
+
+ /**
+ * Returns whether this instance has been finished by a call to {@link #finish}.
+ *
+ * @see WindowInsetsAnimationControlListener#onFinished
+ * @return {@code true} if the instance is finished, {@code false} otherwise.
+ */
+ boolean isFinished();
+
+ /**
+ * Returns whether this instance has been cancelled by the system, or by invoking the
+ * {@link android.os.CancellationSignal} passed into
+ * {@link WindowInsetsController#controlWindowInsetsAnimation}.
+ *
+ * @see WindowInsetsAnimationControlListener#onCancelled
+ * @return {@code true} if the instance is cancelled, {@code false} otherwise.
+ */
+ boolean isCancelled();
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index c5fa3c8..77ce5c1 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -89,6 +89,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -2896,6 +2897,18 @@
private boolean mFitInsetsIgnoringVisibility = false;
/**
+ * {@link InsetsState.InternalInsetsType}s to be applied to the window
+ * If {@link #type} has the predefined insets (like {@link #TYPE_STATUS_BAR} or
+ * {@link #TYPE_NAVIGATION_BAR}), this field will be ignored.
+ *
+ * <p>Note: provide only one inset corresponding to the window type (like
+ * {@link InsetsState.InternalInsetsType#ITYPE_STATUS_BAR} or
+ * {@link InsetsState.InternalInsetsType#ITYPE_NAVIGATION_BAR})</p>
+ * @hide
+ */
+ public @InsetsState.InternalInsetsType int[] providesInsetsTypes;
+
+ /**
* Specifies types of insets that this window should avoid overlapping during layout.
*
* @param types which types of insets that this window should avoid. The initial value of
@@ -3116,6 +3129,12 @@
out.writeInt(mFitInsetsSides);
out.writeBoolean(mFitInsetsIgnoringVisibility);
out.writeBoolean(preferMinimalPostProcessing);
+ if (providesInsetsTypes != null) {
+ out.writeInt(providesInsetsTypes.length);
+ out.writeIntArray(providesInsetsTypes);
+ } else {
+ out.writeInt(0);
+ }
}
public static final @android.annotation.NonNull Parcelable.Creator<LayoutParams> CREATOR
@@ -3177,6 +3196,11 @@
mFitInsetsSides = in.readInt();
mFitInsetsIgnoringVisibility = in.readBoolean();
preferMinimalPostProcessing = in.readBoolean();
+ int insetsTypesLength = in.readInt();
+ if (insetsTypesLength > 0) {
+ providesInsetsTypes = new int[insetsTypesLength];
+ in.readIntArray(providesInsetsTypes);
+ }
}
@SuppressWarnings({"PointlessBitwiseExpression"})
@@ -3437,6 +3461,11 @@
changes |= LAYOUT_CHANGED;
}
+ if (!Arrays.equals(providesInsetsTypes, o.providesInsetsTypes)) {
+ providesInsetsTypes = o.providesInsetsTypes;
+ changes |= LAYOUT_CHANGED;
+ }
+
return changes;
}
@@ -3609,6 +3638,14 @@
sb.append(System.lineSeparator());
sb.append(prefix).append(" fitIgnoreVis");
}
+ if (providesInsetsTypes != null) {
+ sb.append(System.lineSeparator());
+ sb.append(prefix).append(" insetsTypes=");
+ for (int i = 0; i < providesInsetsTypes.length; ++i) {
+ if (i > 0) sb.append(' ');
+ sb.append(InsetsState.typeToString(providesInsetsTypes[i]));
+ }
+ }
sb.append('}');
return sb.toString();
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 5fccf40..4980b33 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -2876,7 +2876,7 @@
}
/**
- * Replaces any ClickableSpans in mText with placeholders.
+ * Replaces any ClickableSpan in the given {@code text} with placeholders.
*
* @param text The text.
*
@@ -2910,7 +2910,7 @@
}
/**
- * Replace any ImageSpans in mText with its content description.
+ * Replaces any ReplacementSpan in the given {@code text} if the object has content description.
*
* @param text The text.
*
diff --git a/core/java/android/view/textclassifier/TextClassificationContext.java b/core/java/android/view/textclassifier/TextClassificationContext.java
index f2323c6..5d5683f 100644
--- a/core/java/android/view/textclassifier/TextClassificationContext.java
+++ b/core/java/android/view/textclassifier/TextClassificationContext.java
@@ -31,7 +31,6 @@
*/
public final class TextClassificationContext implements Parcelable {
- // NOTE: Modify packageName only in the constructor or in setSystemTextClassifierMetadata()
private String mPackageName;
private final String mWidgetType;
@Nullable private final String mWidgetVersion;
@@ -47,7 +46,7 @@
}
/**
- * Returns the package name for the calling package.
+ * Returns the package name of the app that this context originated in.
*/
@NonNull
public String getPackageName() {
@@ -57,14 +56,10 @@
/**
* Sets the information about the {@link SystemTextClassifier} that sent this request.
*
- * <p><b>NOTE: </b>This will override the value returned in {@link getPackageName()}.
* @hide
*/
void setSystemTextClassifierMetadata(@Nullable SystemTextClassifierMetadata systemTcMetadata) {
mSystemTcMetadata = systemTcMetadata;
- if (mSystemTcMetadata != null) {
- mPackageName = mSystemTcMetadata.getCallingPackageName();
- }
}
/**
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 728824c..d661bc6 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -24,7 +24,6 @@
import android.text.method.ArrowKeyMovementMethod;
import android.text.method.MovementMethod;
import android.util.AttributeSet;
-import android.view.accessibility.AccessibilityNodeInfo;
/*
* This is supposed to be a *very* thin veneer over TextView.
@@ -179,13 +178,4 @@
protected boolean supportsAutoSizeText() {
return false;
}
-
- /** @hide */
- @Override
- public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfoInternal(info);
- if (isEnabled()) {
- info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_TEXT);
- }
- }
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 16d9ed3..4aeea10 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -317,6 +317,7 @@
private SelectionActionModeHelper mSelectionActionModeHelper;
boolean mIsBeingLongClicked;
+ boolean mIsBeingLongClickedByAccessibility;
private SuggestionsPopupWindow mSuggestionsPopupWindow;
SuggestionRangeSpan mSuggestionRangeSpan;
@@ -1312,6 +1313,12 @@
if (TextView.DEBUG_CURSOR) {
logCursor("performLongClick", "handled=%s", handled);
}
+ if (mIsBeingLongClickedByAccessibility) {
+ if (!handled) {
+ toggleInsertionActionMode();
+ }
+ return true;
+ }
// Long press in empty space moves cursor and starts the insertion action mode.
if (!handled && !isPositionOnText(mTouchState.getLastDownX(), mTouchState.getLastDownY())
&& !mTouchState.isOnHandle() && mInsertionControllerEnabled) {
@@ -1359,6 +1366,14 @@
return handled;
}
+ private void toggleInsertionActionMode() {
+ if (mTextActionMode != null) {
+ stopTextActionMode();
+ } else {
+ startInsertionActionMode();
+ }
+ }
+
float getLastUpPositionX() {
return mTouchState.getLastUpX();
}
@@ -5436,11 +5451,7 @@
config.getScaledTouchSlop());
if (isWithinTouchSlop) {
// Tapping on the handle toggles the insertion action mode.
- if (mTextActionMode != null) {
- stopTextActionMode();
- } else {
- startInsertionActionMode();
- }
+ toggleInsertionActionMode();
}
} else {
if (mTextActionMode != null) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 2168018..e178318 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -12108,6 +12108,23 @@
onEditorAction(getImeActionId());
}
} return true;
+ case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
+ if (isLongClickable()) {
+ boolean handled;
+ if (isEnabled() && (mBufferType == BufferType.EDITABLE)) {
+ mEditor.mIsBeingLongClickedByAccessibility = true;
+ try {
+ handled = performLongClick();
+ } finally {
+ mEditor.mIsBeingLongClickedByAccessibility = false;
+ }
+ } else {
+ handled = performLongClick();
+ }
+ return handled;
+ }
+ }
+ return false;
default: {
return super.performAccessibilityActionInternal(action, arguments);
}
diff --git a/core/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java b/core/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java
index 9aee879f..ef8d018 100644
--- a/core/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java
+++ b/core/java/com/android/ims/internal/uce/uceservice/ImsUceManager.java
@@ -50,6 +50,16 @@
public static final String ACTION_UCE_SERVICE_DOWN =
"com.android.ims.internal.uce.UCE_SERVICE_DOWN";
+ /**
+ * Uce Service status received in IUceListener.setStatus() callback
+ */
+ public static final int UCE_SERVICE_STATUS_FAILURE = 0;
+ /** indicate UI to call Presence/Options API. */
+ public static final int UCE_SERVICE_STATUS_ON = 1;
+ /** Indicate UI destroy Presence/Options */
+ public static final int UCE_SERVICE_STATUS_CLOSED = 2;
+ /** Service up and trying to register for network events */
+ public static final int UCE_SERVICE_STATUS_READY = 3;
/**
* Gets the instance of UCE Manager
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 503a867..a1a434d 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -1536,10 +1536,12 @@
labels.add(innerInfo.getResolveInfo().loadLabel(getPackageManager()));
}
f = new ResolverTargetActionsDialogFragment(mti.getDisplayLabel(), name,
- mti.getTargets(), labels);
+ mti.getTargets(), labels,
+ mChooserMultiProfilePagerAdapter.getCurrentUserHandle());
} else {
f = new ResolverTargetActionsDialogFragment(
- ti.getResolveInfo().loadLabel(getPackageManager()), name, pinned);
+ ti.getResolveInfo().loadLabel(getPackageManager()), name, pinned,
+ mChooserMultiProfilePagerAdapter.getCurrentUserHandle());
}
f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG);
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 7a0afa2..9bdfa4a 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -38,6 +38,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import android.util.Slog;
import android.widget.Toast;
@@ -153,6 +154,9 @@
}
private boolean shouldShowDisclosure(@Nullable ResolveInfo ri, Intent intent) {
+ if (!isDeviceProvisioned()) {
+ return false;
+ }
if (ri == null || ri.activityInfo == null) {
return true;
}
@@ -163,6 +167,11 @@
return !isTargetResolverOrChooserActivity(ri.activityInfo);
}
+ private boolean isDeviceProvisioned() {
+ return Settings.Global.getInt(getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, /* def= */ 0) != 0;
+ }
+
private boolean isTextMessageIntent(Intent intent) {
return (Intent.ACTION_SENDTO.equals(intent.getAction()) || isViewActionIntent(intent))
&& ALLOWED_TEXT_MESSAGE_SCHEMES.contains(intent.getScheme());
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 086a718..8e64b97 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -49,6 +49,7 @@
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.graphics.Insets;
import android.net.Uri;
import android.os.Build;
@@ -65,6 +66,7 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
+import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -1303,7 +1305,7 @@
Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
- startActivity(in);
+ startActivityAsUser(in, mMultiProfilePagerAdapter.getCurrentUserHandle());
}
@VisibleForTesting
@@ -1606,7 +1608,10 @@
for (int i = 0; i < tabWidget.getChildCount(); i++) {
View tabView = tabWidget.getChildAt(i);
TextView title = tabView.findViewById(android.R.id.title);
- title.setTextColor(getColor(R.color.resolver_tabs_inactive_color));
+ title.setTextAppearance(android.R.style.TextAppearance_DeviceDefault_DialogWindowTitle);
+ title.setTextColor(getAttrColor(this, android.R.attr.textColorTertiary));
+ title.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+ getResources().getDimension(R.dimen.resolver_tab_text_size));
if (title.getText().equals(getString(R.string.resolver_personal_tab))) {
tabView.setContentDescription(personalContentDescription);
} else if (title.getText().equals(getString(R.string.resolver_work_tab))) {
@@ -1615,10 +1620,17 @@
}
}
+ private static int getAttrColor(Context context, int attr) {
+ TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
+ int colorAccent = ta.getColor(0, 0);
+ ta.recycle();
+ return colorAccent;
+ }
+
private void updateActiveTabStyle(TabHost tabHost) {
TextView title = tabHost.getTabWidget().getChildAt(tabHost.getCurrentTab())
.findViewById(android.R.id.title);
- title.setTextColor(getColor(R.color.resolver_tabs_active_color));
+ title.setTextColor(getAttrColor(this, android.R.attr.colorAccent));
}
private void setupViewVisibilities() {
diff --git a/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java b/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
index 21efc78..35d9bcd 100644
--- a/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
+++ b/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java
@@ -27,6 +27,7 @@
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
+import android.os.UserHandle;
import android.provider.Settings;
import com.android.internal.R;
@@ -43,6 +44,7 @@
private static final String NAME_KEY = "componentName";
private static final String TITLE_KEY = "title";
private static final String PINNED_KEY = "pinned";
+ private static final String USER_ID_KEY = "userId";
// Sync with R.array.resolver_target_actions_* resources
private static final int TOGGLE_PIN_INDEX = 0;
@@ -56,19 +58,21 @@
}
public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name,
- boolean pinned) {
+ boolean pinned, UserHandle userHandle) {
Bundle args = new Bundle();
args.putCharSequence(TITLE_KEY, title);
args.putParcelable(NAME_KEY, name);
args.putBoolean(PINNED_KEY, pinned);
+ args.putParcelable(USER_ID_KEY, userHandle);
setArguments(args);
}
public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name,
- List<DisplayResolveInfo> targets, List<CharSequence> labels) {
+ List<DisplayResolveInfo> targets, List<CharSequence> labels, UserHandle userHandle) {
Bundle args = new Bundle();
args.putCharSequence(TITLE_KEY, title);
args.putParcelable(NAME_KEY, name);
+ args.putParcelable(USER_ID_KEY, userHandle);
mTargetInfos = targets;
mLabels = labels;
setArguments(args);
@@ -122,7 +126,8 @@
Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
.setData(Uri.fromParts("package", name.getPackageName(), null))
.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
- startActivity(in);
+ UserHandle userHandle = args.getParcelable(USER_ID_KEY);
+ getActivity().startActivityAsUser(in, userHandle);
}
dismiss();
}
diff --git a/core/java/com/android/internal/os/KernelCpuThreadReader.java b/core/java/com/android/internal/os/KernelCpuThreadReader.java
index d92f725b..3407670 100644
--- a/core/java/com/android/internal/os/KernelCpuThreadReader.java
+++ b/core/java/com/android/internal/os/KernelCpuThreadReader.java
@@ -25,6 +25,7 @@
import com.android.internal.util.Preconditions;
import java.io.IOException;
+import java.nio.file.DirectoryIteratorException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -276,7 +277,7 @@
}
threadCpuUsages.add(threadCpuUsage);
}
- } catch (IOException e) {
+ } catch (IOException | DirectoryIteratorException e) {
// Expected when a process finishes
return null;
}
diff --git a/core/java/com/android/internal/os/KernelCpuThreadReaderDiff.java b/core/java/com/android/internal/os/KernelCpuThreadReaderDiff.java
index ffdc33c..c11b939 100644
--- a/core/java/com/android/internal/os/KernelCpuThreadReaderDiff.java
+++ b/core/java/com/android/internal/os/KernelCpuThreadReaderDiff.java
@@ -16,6 +16,8 @@
package com.android.internal.os;
+import static com.android.internal.util.Preconditions.checkNotNull;
+
import android.annotation.Nullable;
import android.util.ArrayMap;
import android.util.Slog;
@@ -99,7 +101,7 @@
@VisibleForTesting
public KernelCpuThreadReaderDiff(KernelCpuThreadReader reader, int minimumTotalCpuUsageMillis) {
- mReader = reader;
+ mReader = checkNotNull(reader);
mMinimumTotalCpuUsageMillis = minimumTotalCpuUsageMillis;
mPreviousCpuUsage = null;
}
diff --git a/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java b/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java
index fdcc8a8..c908b8c 100644
--- a/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java
+++ b/core/java/com/android/internal/os/KernelCpuThreadReaderSettingsObserver.java
@@ -95,8 +95,10 @@
KernelCpuThreadReader.create(
NUM_BUCKETS_DEFAULT, UidPredicate.fromString(COLLECTED_UIDS_DEFAULT));
mKernelCpuThreadReaderDiff =
- new KernelCpuThreadReaderDiff(
- mKernelCpuThreadReader, MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT);
+ mKernelCpuThreadReader == null
+ ? null
+ : new KernelCpuThreadReaderDiff(
+ mKernelCpuThreadReader, MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT);
}
@Override
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 0eb364d..b32b4ae 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -346,6 +346,22 @@
}
}
+void android_os_Process_enableFreezer(
+ JNIEnv *env, jobject clazz, jboolean enable)
+{
+ bool success = true;
+
+ if (enable) {
+ success = SetTaskProfiles(0, {"FreezerFrozen"}, true);
+ } else {
+ success = SetTaskProfiles(0, {"FreezerThawed"}, true);
+ }
+
+ if (!success) {
+ jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
+ }
+}
+
jint android_os_Process_getProcessGroup(JNIEnv* env, jobject clazz, jint pid)
{
SchedPolicy sp;
@@ -1344,6 +1360,7 @@
{"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
{"sendSignalQuiet", "(II)V", (void*)android_os_Process_sendSignalQuiet},
{"setProcessFrozen", "(IIZ)V", (void*)android_os_Process_setProcessFrozen},
+ {"enableFreezer", "(Z)V", (void*)android_os_Process_enableFreezer},
{"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory},
{"getTotalMemory", "()J", (void*)android_os_Process_getTotalMemory},
{"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V",
diff --git a/core/proto/android/app/appexitinfo.proto b/core/proto/android/app/appexitinfo.proto
index 66173f6..4b9444e 100644
--- a/core/proto/android/app/appexitinfo.proto
+++ b/core/proto/android/app/appexitinfo.proto
@@ -42,4 +42,6 @@
optional int64 rss = 12;
optional int64 timestamp = 13;
optional string description = 14;
+ optional bytes state = 15;
+ optional string trace_file = 16;
}
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index ef6eb38..fc6e639 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -734,6 +734,16 @@
// CATEGORY: SETTINGS
// OS: R
ACTION_SETTINGS_CHANGE_WIFI_HOTSPOT_PASSWORD = 1737;
+
+ // ACTION: Settings > Security > Toggle on Confirm Sim deletion
+ // CATEGORY: SETTINGS
+ // OS: R
+ ACTION_CONFIRM_SIM_DELETION_ON = 1738;
+
+ // ACTION: Settings > Security > Toggle off Confirm Sim deletion
+ // CATEGORY: SETTINGS
+ // OS: R
+ ACTION_CONFIRM_SIM_DELETION_OFF = 1739;
}
/**
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index d6687f0..64cf75d 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -376,8 +376,7 @@
optional bytes system_trace = 3026 [
(section).type = SECTION_FILE,
(section).args = "/data/misc/perfetto-traces/incident-trace",
- (privacy).dest = DEST_AUTOMATIC,
- (section).userdebug_and_eng_only = true
+ (privacy).dest = DEST_AUTOMATIC
];
// Dropbox entries split by tags.
diff --git a/core/proto/android/util/quotatracker.proto b/core/proto/android/util/quotatracker.proto
index 5d022ed..d98e5ee 100644
--- a/core/proto/android/util/quotatracker.proto
+++ b/core/proto/android/util/quotatracker.proto
@@ -131,93 +131,3 @@
// Next tag: 4
}
-
-// A com.android.util.quota.DurationQuotaTracker object.
-message DurationQuotaTrackerProto {
- option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
- optional QuotaTrackerProto base_quota_data = 1;
-
- message DurationLimit {
- option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
- optional CategoryProto category = 1;
- optional int64 limit_ms = 2;
- optional int64 window_size_ms = 3;
- }
- repeated DurationLimit duration_limit = 2;
-
- message ExecutionStats {
- option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
- // The time after which this record should be considered invalid (out of date), in the
- // elapsed realtime timebase.
- optional int64 expiration_time_elapsed = 1;
-
- optional int32 window_size_ms = 2;
- optional int64 duration_limit_ms = 3;
-
- // The overall session duration in the window.
- optional int64 session_duration_in_window_ms = 4;
- // The number of individual long-running events in the window.
- optional int32 event_count_in_window = 5;
-
- // The time after which the app will be under the bucket quota. This is only valid if
- // session_duration_in_window_ms >= duration_limit_ms.
- optional int64 in_quota_time_elapsed = 6;
- }
-
- message Timer {
- option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
- // True if the Timer is actively tracking long-running events.
- optional bool is_active = 1;
- // The time this timer last became active. Only valid if is_active is true.
- optional int64 start_time_elapsed = 2;
- // How many long-running events are currently running. Valid only if is_active is true.
- optional int32 event_count = 3;
- }
-
- message TimingSession {
- option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
- optional int64 start_time_elapsed = 1;
- optional int64 end_time_elapsed = 2;
- // How many events started during this session. This only count long-running events, not
- // instantaneous events.
- optional int32 event_count = 3;
- }
-
- message UptcStats {
- option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
- optional UptcProto uptc = 1;
-
- // True if the UPTC has been given free quota.
- optional bool is_quota_free = 2;
-
- optional Timer timer = 3;
-
- repeated TimingSession saved_sessions = 4;
-
- repeated ExecutionStats execution_stats = 5;
- }
- repeated UptcStats uptc_stats = 3;
-
- message ReachedQuotaAlarmListener {
- option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
- optional int64 trigger_time_elapsed = 1;
-
- message UptcTimes {
- option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
- optional UptcProto uptc = 1;
- optional int64 out_of_quota_time_elapsed = 2;
- }
- repeated UptcTimes uptc_times = 2;
- }
- optional ReachedQuotaAlarmListener reached_quota_alarm_listener = 4;
-
- // Next tag: 5
-}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7a3ec95..ad984e6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -737,7 +737,7 @@
<!-- @SystemApi Allows accessing the messages on ICC
@hide Used internally. -->
<permission android:name="android.permission.ACCESS_MESSAGES_ON_ICC"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Used for runtime permissions related to user's SMS messages. -->
<permission-group android:name="android.permission-group.SMS"
@@ -1109,13 +1109,12 @@
grants your app this permission. If you don't need this permission, be sure your <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
targetSdkVersion}</a> is 4 or higher.
- <p>Protection level: dangerous
+ <p>Protection level: normal
-->
<permission android:name="android.permission.READ_PHONE_STATE"
- android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_readPhoneState"
android:description="@string/permdesc_readPhoneState"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="normal" />
<!-- Allows read access to the device's phone number(s). This is a subset of the capabilities
granted by {@link #READ_PHONE_STATE} but is exposed to instant applications.
@@ -1689,13 +1688,17 @@
<permission android:name="android.permission.NETWORK_FACTORY"
android:protectionLevel="signature" />
+ <!-- @SystemApi @hide Allows applications to access network stats provider -->
+ <permission android:name="android.permission.NETWORK_STATS_PROVIDER"
+ android:protectionLevel="signature" />
+
<!-- Allows Settings and SystemUI to call methods in Networking services
<p>Not for use by third-party or privileged applications.
@SystemApi @TestApi
@hide This should only be used by Settings and SystemUI.
-->
<permission android:name="android.permission.NETWORK_SETTINGS"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows holder to request bluetooth/wifi scan bypassing global "use location" setting and
location permissions.
@@ -1841,7 +1844,7 @@
and bypass OMAPI AccessControlEnforcer.
<p>Not for use by third-party applications.
@hide -->
- <permission android:name="android.permission.SECURE_ELEMENT_PRIVILEGED"
+ <permission android:name="android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION"
android:protectionLevel="signature|privileged" />
<!-- @deprecated This permission used to allow too broad access to sensitive methods and all its
@@ -2136,7 +2139,7 @@
<!-- @SystemApi Allows granting runtime permissions to telephony related components.
@hide -->
<permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows modification of the telephony state - power on, mmi, etc.
Does not include placing calls.
@@ -2164,7 +2167,7 @@
<!-- @SystemApi Allows listen permission to always reported signal strength.
@hide Used internally. -->
<permission android:name="android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Protects the ability to register any PhoneAccount with
PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. This capability indicates that the PhoneAccount
@@ -2277,21 +2280,21 @@
<!-- Must be required by a telephony data service to ensure that only the
system can bind to it.
- <p>Protection level: signature|telephony
+ <p>Protection level: signature
@SystemApi
@hide
-->
<permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Must be required by a NetworkService to ensure that only the
system can bind to it.
- <p>Protection level: signature|telephony
+ <p>Protection level: signature
@SystemApi
@hide
-->
<permission android:name="android.permission.BIND_TELEPHONY_NETWORK_SERVICE"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to manage embedded subscriptions (those on a eUICC)
through EuiccManager APIs.
@@ -2303,19 +2306,19 @@
<!-- @SystemApi Must be required by an EuiccService to ensure that only the system can bind to
it.
- <p>Protection level: signature|telephony
+ <p>Protection level: signature
@hide
-->
<permission android:name="android.permission.BIND_EUICC_SERVICE"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Required for reading information about carrier apps from SystemConfigManager.
- <p>Protection level: signature|telephony
+ <p>Protection level: signature
@SystemApi
@hide
-->
<permission android:name="android.permission.READ_CARRIER_APP_INFO"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- ================================== -->
<!-- Permissions for sdcard interaction -->
@@ -2435,7 +2438,7 @@
types of interactions
@hide -->
<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
- android:protectionLevel="signature|installer|telephony" />
+ android:protectionLevel="signature|installer" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<!-- Allows interaction across profiles in the same profile group. -->
@@ -2673,7 +2676,7 @@
@hide
-->
<permission android:name="android.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows applications like settings to suggest the user's manually chosen time / time zone.
<p>Not for use by third-party applications.
@@ -3095,9 +3098,8 @@
<!-- Allows an application to be the status bar. Currently used only by SystemUI.apk
@hide -->
- // TODO: remove telephony once decouple settings activity from phone process
<permission android:name="android.permission.STATUS_BAR_SERVICE"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows an application to bind to third party quick settings tiles.
<p>Should only be requested by the System, should be required by
@@ -3154,7 +3156,7 @@
@hide
-->
<permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to use
{@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}
@@ -3231,7 +3233,7 @@
@hide
-->
<permission android:name="android.permission.SET_ACTIVITY_WATCHER"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to call the activity manager shutdown() API
to put the higher-level system there into a shutdown state.
@@ -3775,7 +3777,7 @@
@hide
STOPSHIP b/145526313: Remove wellbeing protection flag from MANAGE_ROLE_HOLDERS. -->
<permission android:name="android.permission.MANAGE_ROLE_HOLDERS"
- android:protectionLevel="signature|installer|telephony|wellbeing" />
+ android:protectionLevel="signature|installer|wellbeing" />
<!-- @SystemApi Allows an application to observe role holder changes.
@hide -->
@@ -4012,7 +4014,7 @@
@hide
-->
<permission android:name="android.permission.DEVICE_POWER"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows toggling battery saver on the system.
Superseded by DEVICE_POWER permission. @hide @SystemApi
@@ -4047,13 +4049,13 @@
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.BROADCAST_SMS"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows an application to broadcast a WAP PUSH receipt notification.
<p>Not for use by third-party applications.
-->
<permission android:name="android.permission.BROADCAST_WAP_PUSH"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to broadcast privileged networking requests.
<p>Not for use by third-party applications.
@@ -4719,13 +4721,13 @@
{@link android.provider.BlockedNumberContract}.
@hide -->
<permission android:name="android.permission.READ_BLOCKED_NUMBERS"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Allows the holder to write blocked numbers. See
{@link android.provider.BlockedNumberContract}.
@hide -->
<permission android:name="android.permission.WRITE_BLOCKED_NUMBERS"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- Must be required by an {@link android.service.vr.VrListenerService}, to ensure that only
the system can bind to it.
@@ -4885,7 +4887,7 @@
<!-- @hide Permission that allows configuring appops.
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.MANAGE_APPOPS"
- android:protectionLevel="signature|telephony" />
+ android:protectionLevel="signature" />
<!-- @hide Permission that allows background clipboard access.
<p>Not for use by third-party applications. -->
diff --git a/core/res/res/drawable/tab_indicator_resolver.xml b/core/res/res/drawable/tab_indicator_resolver.xml
index ff16d81a..f97773e 100644
--- a/core/res/res/drawable/tab_indicator_resolver.xml
+++ b/core/res/res/drawable/tab_indicator_resolver.xml
@@ -25,7 +25,7 @@
</item>
<item android:gravity="bottom">
<shape android:shape="rectangle"
- android:tint="@color/resolver_tabs_active_color">
+ android:tint="?attr/colorAccent">
<size android:height="2dp" />
<solid android:color="@color/tab_indicator_material" />
</shape>
diff --git a/core/res/res/layout/resolver_empty_states.xml b/core/res/res/layout/resolver_empty_states.xml
index 176f289..5fdf190 100644
--- a/core/res/res/layout/resolver_empty_states.xml
+++ b/core/res/res/layout/resolver_empty_states.xml
@@ -60,7 +60,7 @@
android:background="@null"
android:fontFamily="@string/config_headlineFontFamilyMedium"
android:textSize="14sp"
- android:textColor="@color/resolver_tabs_active_color"
+ android:textColor="?attr/colorAccent"
android:layout_centerHorizontal="true" />
<ProgressBar
android:id="@+id/resolver_empty_state_progress"
@@ -71,5 +71,5 @@
android:indeterminate="true"
android:layout_centerHorizontal="true"
android:layout_below="@+id/resolver_empty_state_subtitle"
- android:indeterminateTint="@color/resolver_tabs_active_color"/>
+ android:indeterminateTint="?attr/colorAccent"/>
</RelativeLayout>
\ No newline at end of file
diff --git a/core/res/res/values-night/colors.xml b/core/res/res/values-night/colors.xml
index 7f77e6c..708b4f3 100644
--- a/core/res/res/values-night/colors.xml
+++ b/core/res/res/values-night/colors.xml
@@ -33,7 +33,6 @@
<color name="chooser_gradient_background">@color/loading_gradient_background_color_dark</color>
<color name="chooser_gradient_highlight">@color/loading_gradient_highlight_color_dark</color>
- <color name="resolver_tabs_active_color">#FF8AB4F8</color>
<color name="resolver_empty_state_text">#FFFFFF</color>
<color name="resolver_empty_state_icon">#FFFFFF</color>
</resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index f3ca5ac..2496900 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -296,9 +296,6 @@
granted to the system app predictor -->
<flag name="appPredictor" value="0x200000" />
<!-- Additional flag from base permission type: this permission can be automatically
- granted to the system telephony apps -->
- <flag name="telephony" value="0x400000" />
- <!-- Additional flag from base permission type: this permission can be automatically
granted to the system companion device manager service -->
<flag name="companion" value="0x800000" />
<!-- Additional flag from base permission type: this permission will be granted to the
@@ -1835,7 +1832,7 @@
revoked when the app is unused for an extended amount of time.
The default value is {@code false}. -->
- <attr name="requestDontAutoRevokePermissions" format="boolean" />
+ <attr name="requestAutoRevokePermissionsExemption" format="boolean" />
<!-- If {@code true} its permissions shouldn't get automatically
revoked when the app is unused for an extended amount of time.
@@ -1843,7 +1840,7 @@
This implies {@code requestDontAutoRevokePermissions=true}
The default value is {@code false}. -->
- <attr name="allowDontAutoRevokePermissions" format="boolean" />
+ <attr name="allowAutoRevokePermissionsExemption" format="boolean" />
</declare-styleable>
<!-- An attribution is a logical part of an app and is identified by a tag.
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index bdec096..91248f1 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -224,8 +224,6 @@
<!-- Resolver/Chooser -->
<color name="resolver_text_color_secondary_dark">#ffC4C6C6</color>
- <color name="resolver_tabs_active_color">#FF1A73E8</color>
- <color name="resolver_tabs_inactive_color">#FF80868B</color>
<color name="resolver_empty_state_text">#FF202124</color>
<color name="resolver_empty_state_icon">#FF5F6368</color>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6060d9a..94764ca 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2978,6 +2978,10 @@
<!-- Whether to use voip audio mode for ims call -->
<bool name="config_use_voip_mode_for_ims">false</bool>
+ <!-- Boolean indicating USSD over IMS is allowed.
+ If it is not supported due to modem limitations, USSD send over the CS pipe instead.-->
+ <bool name="config_allow_ussd_over_ims">false</bool>
+
<!-- String array containing numbers that shouldn't be logged. Country-specific. -->
<string-array name="unloggable_phone_numbers" />
@@ -3637,15 +3641,6 @@
-->
<string name="config_defaultWellbeingPackage" translatable="false"></string>
- <!-- The package name for the system telephony apps.
- This package must be trusted, as it will be granted with permissions with special telephony
- protection level. Note, framework by default support multiple telephony apps, each package
- name is separated by comma.
- Example: "com.android.phone,com.android.stk,com.android.providers.telephony"
- (Note: shell is included for testing purposes)
- -->
- <string name="config_telephonyPackages" translatable="false">"com.android.phone,com.android.stk,com.android.providers.telephony,com.android.ons"</string>
-
<!-- The component name for the default system attention service.
This service must be trusted, as it can be activated without explicit consent of the user.
See android.attention.AttentionManagerService.
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 15ef09c..4dedc63 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -800,6 +800,7 @@
<dimen name="resolver_empty_state_height_with_tabs">268dp</dimen>
<dimen name="resolver_max_collapsed_height">192dp</dimen>
<dimen name="resolver_max_collapsed_height_with_tabs">248dp</dimen>
+ <dimen name="resolver_tab_text_size">14sp</dimen>
<dimen name="chooser_action_button_icon_size">18dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index cf68aff..5306518 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3014,8 +3014,8 @@
<!-- @hide @SystemApi -->
<public name="minExtensionVersion" />
<public name="allowNativeHeapPointerTagging" />
- <public name="requestDontAutoRevokePermissions" />
- <public name="allowDontAutoRevokePermissions" />
+ <public name="requestAutoRevokePermissionsExemption" />
+ <public name="allowAutoRevokePermissionsExemption" />
<public name="preserveLegacyExternalStorage" />
<public name="mimeGroup" />
<public name="enableGwpAsan" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f101f59..2040bed 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1169,7 +1169,7 @@
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
<string name="permlab_cameraOpenCloseListener">Allow an application or service to receive callbacks about camera devices being opened or closed.</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR_LIMIT=NONE] -->
- <string name="permdesc_cameraOpenCloseListener">This signature app can receive callbacks when any camera device is being opened (by what application package) or closed.</string>
+ <string name="permdesc_cameraOpenCloseListener">This app can receive callbacks when any camera device is being opened (by what application) or closed.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_vibrate">control vibration</string>
@@ -2985,72 +2985,6 @@
<!-- Title for EditText context menu [CHAR LIMIT=20] -->
<string name="editTextMenuTitle">Text actions</string>
- <!-- Label for item in the text selection menu to trigger an Email app. Should be a verb. [CHAR LIMIT=30] -->
- <string name="email">Email</string>
-
- <!-- Accessibility description for an item in the text selection menu to trigger an Email app [CHAR LIMIT=NONE] -->
- <string name="email_desc">Email selected address</string>
-
- <!-- Label for item in the text selection menu to trigger a Dialer app. Should be a verb. [CHAR LIMIT=30] -->
- <string name="dial">Call</string>
-
- <!-- Accessibility description for an item in the text selection menu to call a phone number [CHAR LIMIT=NONE] -->
- <string name="dial_desc">Call selected phone number</string>
-
- <!-- Label for item in the text selection menu to trigger a Map app. Should be a verb. [CHAR LIMIT=30] -->
- <string name="map">Map</string>
-
- <!-- Accessibility description for an item in the text selection menu to open maps for an address [CHAR LIMIT=NONE] -->
- <string name="map_desc">Locate selected address</string>
-
- <!-- Label for item in the text selection menu to trigger a Browser app. Should be a verb. [CHAR LIMIT=30] -->
- <string name="browse">Open</string>
-
- <!-- Accessibility description for an item in the text selection menu to open a URL in a browser [CHAR LIMIT=NONE] -->
- <string name="browse_desc">Open selected URL</string>
-
- <!-- Label for item in the text selection menu to trigger an SMS app. Should be a verb. [CHAR LIMIT=30] -->
- <string name="sms">Message</string>
-
- <!-- Accessibility description for an item in the text selection menu to send an SMS to a phone number [CHAR LIMIT=NONE] -->
- <string name="sms_desc">Message selected phone number</string>
-
- <!-- Label for item in the text selection menu to trigger adding a contact. Should be a verb. [CHAR LIMIT=30] -->
- <string name="add_contact">Add</string>
-
- <!-- Accessibility description for an item in the text selection menu to add the selected detail to contacts [CHAR LIMIT=NONE] -->
- <string name="add_contact_desc">Add to contacts</string>
-
- <!-- Label for item in the text selection menu to view the calendar for the selected time/date. Should be a verb. [CHAR LIMIT=30] -->
- <string name="view_calendar">View</string>
-
- <!-- Accessibility description for an item in the text selection menu to view the calendar for a date [CHAR LIMIT=NONE]-->
- <string name="view_calendar_desc">View selected time in calendar</string>
-
- <!-- Label for item in the text selection menu to create a calendar event at the selected time/date. Should be a verb. [CHAR LIMIT=30] -->
- <string name="add_calendar_event">Schedule</string>
-
- <!-- Accessibility description for an item in the text selection menu to schedule an event for a date [CHAR LIMIT=NONE] -->
- <string name="add_calendar_event_desc">Schedule event for selected time</string>
-
- <!-- Label for item in the text selection menu to track a selected flight number. Should be a verb. [CHAR LIMIT=30] -->
- <string name="view_flight">Track</string>
-
- <!-- Accessibility description for an item in the text selection menu to track a flight [CHAR LIMIT=NONE] -->
- <string name="view_flight_desc">Track selected flight</string>
-
- <!-- Label for item in the text selection menu to translate selected text with a translation app. Should be a verb. [CHAR LIMIT=30] -->
- <string name="translate">Translate</string>
-
- <!-- Accessibility description for an item in the text selection menu to translate selected text with a translation app. [CHAR LIMIT=NONE] -->
- <string name="translate_desc">Translate selected text</string>
-
- <!-- Label for item in the text selection menu to define selected text with a dictionary app. Should be a verb. [CHAR LIMIT=30] -->
- <string name="define">Define</string>
-
- <!-- Accessibility description for an item in the text selection menu to define selected text with a dictionary app. Should be a verb. [CHAR LIMIT=NONE] -->
- <string name="define_desc">Define selected text</string>
-
<!-- If the device is getting low on internal storage, a notification is shown to the user. This is the title of that notification. -->
<string name="low_internal_storage_view_title">Storage space running out</string>
<!-- If the device is getting low on internal storage, a notification is shown to the user. This is the message of that notification. -->
@@ -4510,6 +4444,20 @@
<string name="accessibility_shortcut_spoken_feedback">Press and hold both volume keys for three seconds to use
<xliff:g id="service_name" example="TalkBack">%1$s</xliff:g></string>
+ <!-- Text appearing in a prompt at the top of UI allowing the user to select a target service or feature to be assigned to the Accessibility button in the navigation bar. [CHAR LIMIT=none]-->
+ <string name="accessibility_button_prompt_text">Choose a app to use when you tap the accessibility button:</string>
+ <!-- Text appearing in a prompt at the top of UI allowing the user to select a target service or feature to be assigned to the Accessibility button when gesture navigation is enabled [CHAR LIMIT=none] -->
+ <string name="accessibility_gesture_prompt_text">Choose a app to use with the accessibility gesture (swipe up from the bottom of the screen with two fingers):</string>
+ <!-- Text appearing in a prompt at the top of UI allowing the user to select a target service or feature to be assigned to the Accessibility button when gesture navigation and TalkBack is enabled [CHAR LIMIT=none] -->
+ <string name="accessibility_gesture_3finger_prompt_text">Choose a app to use with the accessibility gesture (swipe up from the bottom of the screen with three fingers):</string>
+
+ <!-- Text describing how to display UI allowing a user to select a target service or feature to be assigned to the Accessibility button in the navigation bar. [CHAR LIMIT=none]-->
+ <string name="accessibility_button_instructional_text">To switch between apps, touch & hold the accessibility button.</string>
+ <!-- Text describing how to display UI allowing a user to select a target service or feature to be assigned to the Accessibility button when gesture navigation is enabled. [CHAR LIMIT=none] -->
+ <string name="accessibility_gesture_instructional_text">To switch between apps, swipe up with two fingers and hold.</string>
+ <!-- Text describing how to display UI allowing a user to select a target service or feature to be assigned to the Accessibility button when gesture navigation and TalkBack is enabled. [CHAR LIMIT=none] -->
+ <string name="accessibility_gesture_3finger_instructional_text">To switch between apps, swipe up with three fingers and hold.</string>
+
<!-- Text used to describe system navigation features, shown within a UI allowing a user to assign system magnification features to the Accessibility button in the navigation bar. -->
<string name="accessibility_magnification_chooser_text">Magnification</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4c0dd8d..a1b00f2 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -551,28 +551,6 @@
<java-symbol type="string" name="replace" />
<java-symbol type="string" name="undo" />
<java-symbol type="string" name="redo" />
- <java-symbol type="string" name="email" />
- <java-symbol type="string" name="email_desc" />
- <java-symbol type="string" name="dial" />
- <java-symbol type="string" name="dial_desc" />
- <java-symbol type="string" name="map" />
- <java-symbol type="string" name="map_desc" />
- <java-symbol type="string" name="browse" />
- <java-symbol type="string" name="browse_desc" />
- <java-symbol type="string" name="sms" />
- <java-symbol type="string" name="sms_desc" />
- <java-symbol type="string" name="add_contact" />
- <java-symbol type="string" name="add_contact_desc" />
- <java-symbol type="string" name="view_calendar" />
- <java-symbol type="string" name="view_calendar_desc" />
- <java-symbol type="string" name="add_calendar_event" />
- <java-symbol type="string" name="add_calendar_event_desc" />
- <java-symbol type="string" name="view_flight" />
- <java-symbol type="string" name="view_flight_desc" />
- <java-symbol type="string" name="translate" />
- <java-symbol type="string" name="translate_desc" />
- <java-symbol type="string" name="define" />
- <java-symbol type="string" name="define_desc" />
<java-symbol type="string" name="textSelectionCABTitle" />
<java-symbol type="string" name="BaMmi" />
<java-symbol type="string" name="CLIRDefaultOffNextCallOff" />
@@ -2553,6 +2531,7 @@
<java-symbol type="bool" name="config_device_wfc_ims_available" />
<java-symbol type="bool" name="config_carrier_wfc_ims_available" />
<java-symbol type="bool" name="config_use_voip_mode_for_ims" />
+ <java-symbol type="bool" name="config_allow_ussd_over_ims" />
<java-symbol type="attr" name="touchscreenBlocksFocus" />
<java-symbol type="layout" name="resolver_list_with_default" />
<java-symbol type="string" name="activity_resolver_set_always" />
@@ -3418,7 +3397,6 @@
<java-symbol type="string" name="config_defaultAutofillService" />
<java-symbol type="string" name="config_defaultTextClassifierPackage" />
<java-symbol type="string" name="config_defaultWellbeingPackage" />
- <java-symbol type="string" name="config_telephonyPackages" />
<java-symbol type="string" name="config_defaultContentCaptureService" />
<java-symbol type="string" name="config_defaultAugmentedAutofillService" />
<java-symbol type="string" name="config_defaultAppPredictionService" />
@@ -3906,8 +3884,6 @@
<java-symbol type="layout" name="conversation_face_pile_layout" />
<!-- Intent resolver and share sheet -->
- <java-symbol type="color" name="resolver_tabs_active_color" />
- <java-symbol type="color" name="resolver_tabs_inactive_color" />
<java-symbol type="string" name="resolver_personal_tab" />
<java-symbol type="string" name="resolver_personal_tab_accessibility" />
<java-symbol type="string" name="resolver_work_tab" />
@@ -3938,6 +3914,7 @@
<java-symbol type="dimen" name="resolver_empty_state_height_with_tabs" />
<java-symbol type="dimen" name="resolver_max_collapsed_height_with_tabs" />
<java-symbol type="bool" name="sharesheet_show_content_preview" />
+ <java-symbol type="dimen" name="resolver_tab_text_size" />
<!-- Toast message for background started foreground service while-in-use permission restriction feature -->
<java-symbol type="string" name="allow_while_in_use_permission_in_fgs" />
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
index 5d42915..4b42f4ae 100644
--- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java
@@ -268,7 +268,7 @@
File snd_stat = new File (root_filepath + "tcp_snd");
int tx = BandwidthTestUtil.parseIntValueFromFile(snd_stat);
NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
- stats.addEntry(NetworkStats.IFACE_ALL, uid, NetworkStats.SET_DEFAULT,
+ stats.insertEntry(NetworkStats.IFACE_ALL, uid, NetworkStats.SET_DEFAULT,
NetworkStats.TAG_NONE, rx, 0, tx, 0, 0);
return stats;
}
diff --git a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
index 239f971..3ebe103 100644
--- a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
+++ b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
@@ -54,7 +54,7 @@
recycle.txBytes = 150000;
recycle.txPackets = 1500;
recycle.operations = 0;
- mNetworkStats.addEntry(recycle);
+ mNetworkStats.insertEntry(recycle);
if (recycle.set == 1) {
uid++;
}
@@ -70,7 +70,7 @@
recycle.txBytes = 180000 * mSize;
recycle.txPackets = 1200 * mSize;
recycle.operations = 0;
- mNetworkStats.addEntry(recycle);
+ mNetworkStats.insertEntry(recycle);
}
}
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index c328d72..90d8bab 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -40,7 +40,10 @@
import android.app.servertransaction.StopActivityItem;
import android.content.Intent;
import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Rect;
import android.os.IBinder;
+import android.util.DisplayMetrics;
import android.util.MergedConfiguration;
import android.view.Display;
import android.view.View;
@@ -307,6 +310,58 @@
}
@Test
+ public void testHandleConfigurationChangedDoesntOverrideActivityConfig() {
+ final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ final Configuration oldActivityConfig =
+ new Configuration(activity.getResources().getConfiguration());
+ final DisplayMetrics oldActivityMetrics = new DisplayMetrics();
+ activity.getDisplay().getMetrics(oldActivityMetrics);
+ final Resources oldAppResources = activity.getApplication().getResources();
+ final Configuration oldAppConfig =
+ new Configuration(oldAppResources.getConfiguration());
+ final DisplayMetrics oldApplicationMetrics = new DisplayMetrics();
+ oldApplicationMetrics.setTo(oldAppResources.getDisplayMetrics());
+ assertEquals("Process config must match the top activity config by default",
+ 0, oldActivityConfig.diffPublicOnly(oldAppConfig));
+ assertEquals("Process config must match the top activity config by default",
+ oldActivityMetrics, oldApplicationMetrics);
+
+ // Update the application configuration separately from activity config
+ final Configuration newAppConfig = new Configuration(oldAppConfig);
+ newAppConfig.densityDpi += 100;
+ newAppConfig.screenHeightDp += 100;
+ final Rect newBounds = new Rect(newAppConfig.windowConfiguration.getAppBounds());
+ newBounds.bottom += 100;
+ newAppConfig.windowConfiguration.setAppBounds(newBounds);
+ newAppConfig.windowConfiguration.setBounds(newBounds);
+ newAppConfig.seq++;
+
+ final ActivityThread activityThread = activity.getActivityThread();
+ activityThread.handleConfigurationChanged(newAppConfig);
+
+ // Verify that application config update was applied, but didn't change activity config.
+ assertEquals("Activity config must not change if the process config changes",
+ oldActivityConfig, activity.getResources().getConfiguration());
+
+ final DisplayMetrics newActivityMetrics = new DisplayMetrics();
+ activity.getDisplay().getMetrics(newActivityMetrics);
+ assertEquals("Activity display size must not change if the process config changes",
+ oldActivityMetrics, newActivityMetrics);
+ final Resources newAppResources = activity.getApplication().getResources();
+ assertEquals("Application config must be updated",
+ newAppConfig, newAppResources.getConfiguration());
+ final DisplayMetrics newApplicationMetrics = new DisplayMetrics();
+ newApplicationMetrics.setTo(newAppResources.getDisplayMetrics());
+ assertNotEquals("Application display size must be updated after config update",
+ oldApplicationMetrics, newApplicationMetrics);
+ assertNotEquals("Application display size must be updated after config update",
+ newActivityMetrics, newApplicationMetrics);
+ });
+ }
+
+ @Test
public void testResumeAfterNewIntent() {
final Activity activity = mActivityTestRule.launchActivity(new Intent());
final ActivityThread activityThread = activity.getActivityThread();
diff --git a/core/tests/coretests/src/android/app/timezonedetector/ManualTimeZoneSuggestionTest.java b/core/tests/coretests/src/android/app/timezonedetector/ManualTimeZoneSuggestionTest.java
index 02ed0ed..17838bb1 100644
--- a/core/tests/coretests/src/android/app/timezonedetector/ManualTimeZoneSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/timezonedetector/ManualTimeZoneSuggestionTest.java
@@ -18,12 +18,19 @@
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
+import static android.app.timezonedetector.ShellCommandTestSupport.createShellCommandWithArgsAndOptions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.os.ShellCommand;
import org.junit.Test;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
public class ManualTimeZoneSuggestionTest {
private static final String ARBITRARY_ZONE_ID1 = "Europe/London";
@@ -58,4 +65,36 @@
ManualTimeZoneSuggestion rtSuggestion = roundTripParcelable(suggestion);
assertEquals(suggestion.getDebugInfo(), rtSuggestion.getDebugInfo());
}
+
+ @Test
+ public void testPrintCommandLineOpts() throws Exception {
+ try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
+ ManualTimeZoneSuggestion.printCommandLineOpts(pw);
+ assertTrue(sw.getBuffer().length() > 0);
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noArgs() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions("");
+ ManualTimeZoneSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test
+ public void testParseCommandLineArg_validSuggestion() {
+ ShellCommand testShellCommand =
+ createShellCommandWithArgsAndOptions("--zone_id Europe/London");
+ ManualTimeZoneSuggestion expectedSuggestion =
+ new ManualTimeZoneSuggestion("Europe/London");
+ ManualTimeZoneSuggestion actualSuggestion =
+ ManualTimeZoneSuggestion.parseCommandLineArg(testShellCommand);
+ assertEquals(expectedSuggestion, actualSuggestion);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_unknownArgument() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--zone_id Europe/London --bad_arg 0");
+ ManualTimeZoneSuggestion.parseCommandLineArg(testShellCommand);
+ }
}
diff --git a/core/tests/coretests/src/android/app/timezonedetector/ShellCommandTestSupport.java b/core/tests/coretests/src/android/app/timezonedetector/ShellCommandTestSupport.java
new file mode 100644
index 0000000..8d8290c
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timezonedetector/ShellCommandTestSupport.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 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.app.timezonedetector;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.os.ShellCommand;
+
+import org.mockito.stubbing.Answer;
+
+import java.util.Arrays;
+import java.util.List;
+
+/** Utility methods related to {@link ShellCommand} objects used in several tests. */
+final class ShellCommandTestSupport {
+ private ShellCommandTestSupport() {}
+
+ static ShellCommand createShellCommandWithArgsAndOptions(String argsWithSpaces) {
+ return createShellCommandWithArgsAndOptions(Arrays.asList(argsWithSpaces.split(" ")));
+ }
+
+ static ShellCommand createShellCommandWithArgsAndOptions(List<String> args) {
+ ShellCommand command = mock(ShellCommand.class);
+ class ArgProvider {
+ private int mCount;
+
+ String getNext() {
+ if (mCount >= args.size()) {
+ return null;
+ }
+ return args.get(mCount++);
+ }
+
+ String getNextRequired() {
+ String next = getNext();
+ if (next == null) {
+ throw new IllegalArgumentException("No next");
+ }
+ return next;
+ }
+ }
+ ArgProvider argProvider = new ArgProvider();
+ when(command.getNextArg()).thenAnswer(
+ (Answer<String>) invocation -> argProvider.getNext());
+ when(command.getNextOption()).thenAnswer(
+ (Answer<String>) invocation -> argProvider.getNext());
+ when(command.getNextArgRequired()).thenAnswer(
+ (Answer<String>) invocation -> argProvider.getNextRequired());
+ return command;
+ }
+}
diff --git a/core/tests/coretests/src/android/app/timezonedetector/TelephonyTimeZoneSuggestionTest.java b/core/tests/coretests/src/android/app/timezonedetector/TelephonyTimeZoneSuggestionTest.java
index 59d55b7..c4ff9be 100644
--- a/core/tests/coretests/src/android/app/timezonedetector/TelephonyTimeZoneSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/timezonedetector/TelephonyTimeZoneSuggestionTest.java
@@ -18,13 +18,19 @@
import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
+import static android.app.timezonedetector.ShellCommandTestSupport.createShellCommandWithArgsAndOptions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
+import android.os.ShellCommand;
+
import org.junit.Test;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
public class TelephonyTimeZoneSuggestionTest {
private static final int SLOT_INDEX = 99999;
@@ -159,4 +165,57 @@
assertEquals(suggestion1, suggestion1_2);
assertTrue(suggestion1_2.getDebugInfo().contains(debugString));
}
+
+ @Test
+ public void testPrintCommandLineOpts() throws Exception {
+ try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
+ TelephonyTimeZoneSuggestion.printCommandLineOpts(pw);
+ assertTrue(sw.getBuffer().length() > 0);
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noArgs() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions("");
+ TelephonyTimeZoneSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_noSlotIndex() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions("--zone_id _");
+ TelephonyTimeZoneSuggestion.parseCommandLineArg(testShellCommand);
+ }
+
+ @Test
+ public void testParseCommandLineArg_validEmptyZoneIdSuggestion() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--slot_index 0 --zone_id _");
+ TelephonyTimeZoneSuggestion expectedSuggestion =
+ new TelephonyTimeZoneSuggestion.Builder(0).build();
+ TelephonyTimeZoneSuggestion actualSuggestion =
+ TelephonyTimeZoneSuggestion.parseCommandLineArg(testShellCommand);
+ assertEquals(expectedSuggestion, actualSuggestion);
+ }
+
+ @Test
+ public void testParseCommandLineArg_validNonEmptySuggestion() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--slot_index 0 --zone_id Europe/London --quality single --match_type country");
+ TelephonyTimeZoneSuggestion expectedSuggestion =
+ new TelephonyTimeZoneSuggestion.Builder(0)
+ .setZoneId("Europe/London")
+ .setQuality(TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE)
+ .setMatchType(TelephonyTimeZoneSuggestion.MATCH_TYPE_NETWORK_COUNTRY_ONLY)
+ .build();
+ TelephonyTimeZoneSuggestion actualSuggestion =
+ TelephonyTimeZoneSuggestion.parseCommandLineArg(testShellCommand);
+ assertEquals(expectedSuggestion, actualSuggestion);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testParseCommandLineArg_unknownArgument() {
+ ShellCommand testShellCommand = createShellCommandWithArgsAndOptions(
+ "--slot_index 0 --zone_id _ --bad_arg 0");
+ TelephonyTimeZoneSuggestion.parseCommandLineArg(testShellCommand);
+ }
}
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index fe25e79..c87433f 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -16,13 +16,14 @@
package android.view;
-import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_SHOWN;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowInsets.Type.systemBars;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -135,6 +136,13 @@
}
@Test
+ public void testReady() {
+ assertTrue(mController.isReady());
+ assertFalse(mController.isFinished());
+ assertFalse(mController.isCancelled());
+ }
+
+ @Test
public void testChangeInsets() {
mController.setInsetsAndAlpha(Insets.of(0, 30, 40, 0), 1f /* alpha */,
0f /* fraction */);
@@ -178,6 +186,10 @@
mController.applyChangeInsets(mInsetsState);
assertEquals(Insets.of(0, 100, 100, 0), mController.getCurrentInsets());
verify(mMockController).notifyFinished(eq(mController), eq(true /* shown */));
+ assertFalse(mController.isReady());
+ assertTrue(mController.isFinished());
+ assertFalse(mController.isCancelled());
+ verify(mMockListener).onFinished(mController);
}
@Test
@@ -188,7 +200,10 @@
fail("Expected exception to be thrown");
} catch (IllegalStateException ignored) {
}
- verify(mMockListener).onCancelled();
+ assertFalse(mController.isReady());
+ assertFalse(mController.isFinished());
+ assertTrue(mController.isCancelled());
+ verify(mMockListener).onCancelled(mController);
mController.finish(true /* shown */);
}
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 42ab2e7..b449bb0 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -195,6 +195,9 @@
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
+ ArgumentCaptor<WindowInsetsAnimationController> animationController =
+ ArgumentCaptor.forClass(WindowInsetsAnimationController.class);
+
WindowInsetsAnimationControlListener mockListener =
mock(WindowInsetsAnimationControlListener.class);
mController.controlWindowInsetsAnimation(statusBars(), 10 /* durationMs */,
@@ -202,9 +205,10 @@
// Ready gets deferred until next predraw
mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
- verify(mockListener).onReady(any(), anyInt());
+ verify(mockListener).onReady(animationController.capture(), anyInt());
mController.onControlsChanged(new InsetsSourceControl[0]);
- verify(mockListener).onCancelled();
+ verify(mockListener).onCancelled(notNull());
+ assertTrue(animationController.getValue().isCancelled());
});
}
@@ -221,7 +225,7 @@
new CancellationSignal(), controlListener);
mController.addOnControllableInsetsChangedListener(
(controller, typeMask) -> assertEquals(0, typeMask));
- verify(controlListener).onCancelled();
+ verify(controlListener).onCancelled(null);
verify(controlListener, never()).onReady(any(), anyInt());
}
@@ -533,7 +537,7 @@
verify(mockListener).onReady(any(), anyInt());
cancellationSignal.cancel();
- verify(mockListener).onCancelled();
+ verify(mockListener).onCancelled(notNull());
});
waitUntilNextFrame();
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
@@ -584,7 +588,7 @@
// Pretend that we are losing control
mController.onControlsChanged(new InsetsSourceControl[0]);
- verify(listener).onCancelled();
+ verify(listener).onCancelled(null);
});
}
@@ -606,7 +610,7 @@
mTestClock.fastForward(2500);
mTestHandler.timeAdvance();
- verify(listener).onCancelled();
+ verify(listener).onCancelled(null);
});
}
@@ -621,7 +625,7 @@
cancellationSignal, listener);
cancellationSignal.cancel();
- verify(listener).onCancelled();
+ verify(listener).onCancelled(null);
// Ready gets deferred until next predraw
mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
diff --git a/core/tests/coretests/src/android/view/PendingInsetsControllerTest.java b/core/tests/coretests/src/android/view/PendingInsetsControllerTest.java
index 33f859e..03c8b1b 100644
--- a/core/tests/coretests/src/android/view/PendingInsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/PendingInsetsControllerTest.java
@@ -99,7 +99,7 @@
CancellationSignal cancellationSignal = new CancellationSignal();
mPendingInsetsController.controlWindowInsetsAnimation(
systemBars(), 0, new LinearInterpolator(), cancellationSignal, listener);
- verify(listener).onCancelled();
+ verify(listener).onCancelled(null);
assertFalse(cancellationSignal.isCanceled());
}
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index a72be25..45d4b38 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -65,6 +65,7 @@
import android.app.Instrumentation;
import android.content.ClipData;
import android.content.ClipboardManager;
+import android.os.Bundle;
import android.support.test.uiautomator.UiDevice;
import android.text.InputType;
import android.text.Selection;
@@ -75,6 +76,7 @@
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.view.textclassifier.SelectionEvent;
import android.view.textclassifier.TextClassificationManager;
import android.view.textclassifier.TextClassifier;
@@ -358,6 +360,20 @@
}
@Test
+ public void testToolbarAppearsAccessibilityLongClick() throws Throwable {
+ final String text = "Toolbar appears after performing accessibility's ACTION_LONG_CLICK.";
+ mActivityRule.runOnUiThread(() -> {
+ final TextView textView = mActivity.findViewById(R.id.textview);
+ final Bundle args = new Bundle();
+ textView.performAccessibilityAction(AccessibilityNodeInfo.ACTION_LONG_CLICK, args);
+ });
+ mInstrumentation.waitForIdleSync();
+
+ sleepForFloatingToolbarPopup();
+ assertFloatingToolbarIsDisplayed();
+ }
+
+ @Test
public void testSelectionRemovedWhenNonselectableTextLosesFocus() throws Throwable {
final TextLinks.TextLink textLink = addLinkifiedTextToTextView(R.id.nonselectable_textview);
final int position = (textLink.getStart() + textLink.getEnd()) / 2;
diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
index abfb4fb..8cf146e 100644
--- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
@@ -48,6 +48,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Settings;
import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
@@ -56,6 +57,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -87,6 +89,7 @@
static {
MANAGED_PROFILE_INFO.id = 10;
MANAGED_PROFILE_INFO.flags = UserInfo.FLAG_MANAGED_PROFILE;
+ MANAGED_PROFILE_INFO.userType = UserManager.USER_TYPE_PROFILE_MANAGED;
}
private static UserInfo CURRENT_USER_INFO = new UserInfo();
@@ -116,12 +119,21 @@
private Context mContext;
public static final String PHONE_NUMBER = "123-456-789";
+ private int mDeviceProvisionedInitialValue;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mContext = InstrumentationRegistry.getTargetContext();
sInjector = spy(new TestInjector());
+ mDeviceProvisionedInitialValue = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, /* def= */ 0);
+ }
+
+ @After
+ public void tearDown() {
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED,
+ mDeviceProvisionedInitialValue);
}
@Test
@@ -533,6 +545,22 @@
}
@Test
+ public void shouldSkipDisclosure_duringDeviceSetup() throws RemoteException {
+ setupShouldSkipDisclosureTest();
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED,
+ /* value= */ 0);
+ Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class)
+ .setAction(Intent.ACTION_VIEW)
+ .addCategory(Intent.CATEGORY_BROWSABLE)
+ .setData(Uri.fromParts("http", "apache.org", null));
+
+ mActivityRule.launchActivity(intent);
+
+ verify(mIPm).canForwardTo(any(), any(), anyInt(), anyInt());
+ verify(sInjector, never()).showToast(anyInt(), anyInt());
+ }
+
+ @Test
public void forwardToManagedProfile_LoggingTest() throws Exception {
sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME;
@@ -590,6 +618,8 @@
sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME;
sActivityName = "MyTestActivity";
sPackageName = "test.package.name";
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED,
+ /* value= */ 1);
when(mApplicationInfo.isSystemApp()).thenReturn(true);
// Managed profile exists.
List<UserInfo> profiles = new ArrayList<>();
diff --git a/data/etc/com.android.launcher3.xml b/data/etc/com.android.launcher3.xml
index 337e153..17d614e 100644
--- a/data/etc/com.android.launcher3.xml
+++ b/data/etc/com.android.launcher3.xml
@@ -19,5 +19,6 @@
<permission name="android.permission.BIND_APPWIDGET"/>
<permission name="android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"/>
<permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
+ <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
</privapp-permissions>
</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 5466ac8..87b0817 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -36,11 +36,6 @@
<permission name="android.permission.CRYPT_KEEPER"/>
</privapp-permissions>
- <privapp-permissions package="com.android.captiveportallogin">
- <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
- <permission name="android.permission.NETWORK_BYPASS_PRIVATE_DNS"/>
- </privapp-permissions>
-
<privapp-permissions package="com.android.cellbroadcastreceiver">
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.MANAGE_USERS"/>
@@ -400,6 +395,8 @@
<permission name="android.permission.COMPANION_APPROVE_WIFI_CONNECTIONS" />
<!-- Permission required for testing registering pull atom callbacks. -->
<permission name="android.permission.REGISTER_STATS_PULL_ATOM"/>
+ <!-- Permission required for testing system audio effect APIs. -->
+ <permission name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS"/>
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/location/java/android/location/AbstractListenerManager.java b/location/java/android/location/AbstractListenerManager.java
index 3dc7cfc..36b8689 100644
--- a/location/java/android/location/AbstractListenerManager.java
+++ b/location/java/android/location/AbstractListenerManager.java
@@ -85,11 +85,13 @@
}
}
- @GuardedBy("mListeners")
- private final ArrayMap<Object, Registration<TRequest, TListener>> mListeners =
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private volatile ArrayMap<Object, Registration<TRequest, TListener>> mListeners =
new ArrayMap<>();
- @GuardedBy("mListeners")
+ @GuardedBy("mLock")
@Nullable
private TRequest mMergedRequest;
@@ -129,10 +131,16 @@
throws RemoteException {
Preconditions.checkNotNull(registration);
- synchronized (mListeners) {
+ synchronized (mLock) {
boolean initialRequest = mListeners.isEmpty();
- Registration<TRequest, TListener> oldRegistration = mListeners.put(key, registration);
+ ArrayMap<Object, Registration<TRequest, TListener>> newListeners = new ArrayMap<>(
+ mListeners.size() + 1);
+ newListeners.putAll(mListeners);
+ Registration<TRequest, TListener> oldRegistration = newListeners.put(key,
+ registration);
+ mListeners = newListeners;
+
if (oldRegistration != null) {
oldRegistration.unregister();
}
@@ -151,8 +159,12 @@
}
public void removeListener(Object listener) throws RemoteException {
- synchronized (mListeners) {
- Registration<TRequest, TListener> oldRegistration = mListeners.remove(listener);
+ synchronized (mLock) {
+ ArrayMap<Object, Registration<TRequest, TListener>> newListeners = new ArrayMap<>(
+ mListeners);
+ Registration<TRequest, TListener> oldRegistration = newListeners.remove(listener);
+ mListeners = newListeners;
+
if (oldRegistration == null) {
return;
}
@@ -190,18 +202,16 @@
}
protected void execute(Consumer<TListener> operation) {
- synchronized (mListeners) {
- for (Registration<TRequest, TListener> registration : mListeners.values()) {
- registration.execute(operation);
- }
+ for (Registration<TRequest, TListener> registration : mListeners.values()) {
+ registration.execute(operation);
}
}
- @GuardedBy("mListeners")
+ @GuardedBy("mLock")
@SuppressWarnings("unchecked")
@Nullable
private TRequest mergeRequests() {
- Preconditions.checkState(Thread.holdsLock(mListeners));
+ Preconditions.checkState(Thread.holdsLock(mLock));
if (mListeners.isEmpty()) {
return null;
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 83a8995..5e3b8aa 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -21,8 +21,8 @@
import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_CARRIER_FREQUENCY;
import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_CARRIER_PHASE;
import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_CARRIER_PHASE_UNCERTAINTY;
-import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_RECEIVER_ISB;
-import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_RECEIVER_ISB_UNCERTAINTY;
+import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_FULL_ISB;
+import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_FULL_ISB_UNCERTAINTY;
import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_SATELLITE_ISB;
import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_SATELLITE_ISB_UNCERTAINTY;
import static android.hardware.gnss.V2_1.IGnssMeasurementCallback.GnssMeasurementFlags.HAS_SNR;
@@ -63,8 +63,8 @@
private double mSnrInDb;
private double mAutomaticGainControlLevelInDb;
@NonNull private String mCodeType;
- private double mReceiverInterSignalBiasNanos;
- private double mReceiverInterSignalBiasUncertaintyNanos;
+ private double mFullInterSignalBiasNanos;
+ private double mFullInterSignalBiasUncertaintyNanos;
private double mSatelliteInterSignalBiasNanos;
private double mSatelliteInterSignalBiasUncertaintyNanos;
@@ -268,9 +268,9 @@
mSnrInDb = measurement.mSnrInDb;
mAutomaticGainControlLevelInDb = measurement.mAutomaticGainControlLevelInDb;
mCodeType = measurement.mCodeType;
- mReceiverInterSignalBiasNanos = measurement.mReceiverInterSignalBiasNanos;
- mReceiverInterSignalBiasUncertaintyNanos =
- measurement.mReceiverInterSignalBiasUncertaintyNanos;
+ mFullInterSignalBiasNanos = measurement.mFullInterSignalBiasNanos;
+ mFullInterSignalBiasUncertaintyNanos =
+ measurement.mFullInterSignalBiasUncertaintyNanos;
mSatelliteInterSignalBiasNanos = measurement.mSatelliteInterSignalBiasNanos;
mSatelliteInterSignalBiasUncertaintyNanos =
measurement.mSatelliteInterSignalBiasUncertaintyNanos;
@@ -1435,99 +1435,110 @@
}
/**
- * Returns {@code true} if {@link #getReceiverInterSignalBiasNanos()} is available,
+ * Returns {@code true} if {@link #getFullInterSignalBiasNanos()} is available,
* {@code false} otherwise.
*/
- public boolean hasReceiverInterSignalBiasNanos() {
- return isFlagSet(HAS_RECEIVER_ISB);
+ public boolean hasFullInterSignalBiasNanos() {
+ return isFlagSet(HAS_FULL_ISB);
}
/**
- * Gets the GNSS measurement's receiver inter-signal bias in nanoseconds with sub-nanosecond
- * accuracy.
+ * Gets the GNSS measurement's inter-signal bias in nanoseconds with sub-nanosecond accuracy.
*
- * <p>This value is the estimated receiver-side inter-system (different from the
- * constellation in {@link GnssClock#getReferenceConstellationTypeForIsb()} bias and
- * inter-frequency (different from the carrier frequency in
- * {@link GnssClock#getReferenceCarrierFrequencyHzForIsb()}) bias. The reported receiver
- * inter-signal bias must include signal delays caused by:
+ * <p>This value is the sum of the estimated receiver-side and the space-segment-side
+ * inter-system bias, inter-frequency bias and inter-code bias, including:
*
* <ul>
- * <li>Receiver inter-constellation bias</li>
- * <li>Receiver inter-frequency bias</li>
- * <li>Receiver inter-code bias</li>
+ * <li>Receiver inter-constellation bias (with respect to the constellation in
+ * {@link GnssClock#getReferenceConstellationTypeForIsb())</li>
+ * <li>Receiver inter-frequency bias (with respect to the carrier frequency in
+ * {@link GnssClock#getReferenceConstellationTypeForIsb())</li>
+ * <li>Receiver inter-code bias (with respect to the code type in
+ * {@link GnssClock#getReferenceConstellationTypeForIsb())</li>
+ * <li>Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPS-UTC Time Offset (TauGps),
+ * BDS-GLO Time Offset (BGTO))(with respect to the constellation in
+ * {@link GnssClock#getReferenceConstellationTypeForIsb())</li>
+ * <li>Group delay (e.g., Total Group Delay (TGD))</li>
+ * <li>Satellite inter-frequency bias (GLO only) (with respect to the carrier frequency in
+ * {@link GnssClock#getReferenceConstellationTypeForIsb())</li>
+ * <li>Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the code
+ * type in {@link GnssClock#getReferenceConstellationTypeForIsb())</li>
* </ul>
*
+ * <p>If a component of the above is already compensated in the provided
+ * {@link GnssMeasurement#getReceivedSvTimeNanos()}, then it must not be included in the
+ * reported full ISB.
+ *
* <p>The value does not include the inter-frequency Ionospheric bias.
*
- * <p>The value is only available if {@link #hasReceiverInterSignalBiasNanos()} is {@code true}.
+ * <p>The value is only available if {@link #hasFullInterSignalBiasNanos()} is {@code true}.
*/
- public double getReceiverInterSignalBiasNanos() {
- return mReceiverInterSignalBiasNanos;
+ public double getFullInterSignalBiasNanos() {
+ return mFullInterSignalBiasNanos;
}
/**
- * Sets the GNSS measurement's receiver inter-signal bias in nanoseconds.
+ * Sets the GNSS measurement's inter-signal bias in nanoseconds.
*
* @hide
*/
@TestApi
- public void setReceiverInterSignalBiasNanos(double receiverInterSignalBiasNanos) {
- setFlag(HAS_RECEIVER_ISB);
- mReceiverInterSignalBiasNanos = receiverInterSignalBiasNanos;
+ public void setFullInterSignalBiasNanos(double fullInterSignalBiasNanos) {
+ setFlag(HAS_FULL_ISB);
+ mFullInterSignalBiasNanos = fullInterSignalBiasNanos;
}
/**
- * Resets the GNSS measurement's receiver inter-signal bias in nanoseconds.
+ * Resets the GNSS measurement's inter-signal bias in nanoseconds.
*
* @hide
*/
@TestApi
- public void resetReceiverInterSignalBiasNanos() {
- resetFlag(HAS_RECEIVER_ISB);
+ public void resetFullInterSignalBiasNanos() {
+ resetFlag(HAS_FULL_ISB);
}
/**
- * Returns {@code true} if {@link #getReceiverInterSignalBiasUncertaintyNanos()} is available,
+ * Returns {@code true} if {@link #getFullInterSignalBiasUncertaintyNanos()} is available,
* {@code false} otherwise.
*/
- public boolean hasReceiverInterSignalBiasUncertaintyNanos() {
- return isFlagSet(HAS_RECEIVER_ISB_UNCERTAINTY);
+ public boolean hasFullInterSignalBiasUncertaintyNanos() {
+ return isFlagSet(HAS_FULL_ISB_UNCERTAINTY);
}
/**
- * Gets the GNSS measurement's receiver inter-signal bias uncertainty (1 sigma) in
+ * Gets the GNSS measurement's inter-signal bias uncertainty (1 sigma) in
* nanoseconds with sub-nanosecond accuracy.
*
- * <p>The value is only available if {@link #hasReceiverInterSignalBiasUncertaintyNanos()} is
+ * <p>The value is only available if {@link #hasFullInterSignalBiasUncertaintyNanos()} is
* {@code true}.
*/
@FloatRange(from = 0.0)
- public double getReceiverInterSignalBiasUncertaintyNanos() {
- return mReceiverInterSignalBiasUncertaintyNanos;
+ public double getFullInterSignalBiasUncertaintyNanos() {
+ return mFullInterSignalBiasUncertaintyNanos;
}
/**
- * Sets the GNSS measurement's receiver inter-signal bias uncertainty (1 sigma) in nanoseconds.
+ * Sets the GNSS measurement's inter-signal bias uncertainty (1 sigma) in nanoseconds.
*
* @hide
*/
@TestApi
- public void setReceiverInterSignalBiasUncertaintyNanos(@FloatRange(from = 0.0)
- double receiverInterSignalBiasUncertaintyNanos) {
- setFlag(HAS_RECEIVER_ISB_UNCERTAINTY);
- mReceiverInterSignalBiasUncertaintyNanos = receiverInterSignalBiasUncertaintyNanos;
+ public void setFullInterSignalBiasUncertaintyNanos(@FloatRange(from = 0.0)
+ double fullInterSignalBiasUncertaintyNanos) {
+ setFlag(HAS_FULL_ISB_UNCERTAINTY);
+ mFullInterSignalBiasUncertaintyNanos = fullInterSignalBiasUncertaintyNanos;
}
/**
- * Resets the GNSS measurement's receiver inter-signal bias uncertainty (1 sigma) in
+ * Resets the GNSS measurement's inter-signal bias uncertainty (1 sigma) in
* nanoseconds.
*
* @hide
*/
@TestApi
- public void resetReceiverInterSignalBiasUncertaintyNanos() {
- resetFlag(HAS_RECEIVER_ISB_UNCERTAINTY);
+ public void resetFullInterSignalBiasUncertaintyNanos() {
+ resetFlag(HAS_FULL_ISB_UNCERTAINTY);
}
/**
@@ -1542,17 +1553,18 @@
* Gets the GNSS measurement's satellite inter-signal bias in nanoseconds with sub-nanosecond
* accuracy.
*
- * <p>This value is the satellite-and-control-segment-side inter-system (different from the
- * constellation in {@link GnssClock#getReferenceConstellationTypeForIsb()}) bias and
- * inter-frequency (different from the carrier frequency in
- * {@link GnssClock#getReferenceCarrierFrequencyHzForIsb()}) bias, including:
+ * <p>This value is the space-segment-side inter-system bias, inter-frequency bias and
+ * inter-code bias, including:
*
* <ul>
- * <li>Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPT-UTC Time Offset (TauGps),
- * BDS-GLO Time Offset (BGTO))</li>
+ * <li>Master clock bias (e.g., GPS-GAL Time Offset (GGTO), GPS-UTC Time Offset (TauGps),
+ * BDS-GLO Time Offset (BGTO))(with respect to the constellation in
+ * {@link GnssClock#getReferenceConstellationTypeForIsb())</li>
* <li>Group delay (e.g., Total Group Delay (TGD))</li>
- * <li>Satellite inter-signal bias, which includes satellite inter-frequency bias (GLO only),
- * and satellite inter-code bias (e.g., Differential Code Bias (DCB)).</li>
+ * <li>Satellite inter-frequency bias (GLO only) (with respect to the carrier frequency in
+ * {@link GnssClock#getReferenceConstellationTypeForIsb())</li>
+ * <li>Satellite inter-code bias (e.g., Differential Code Bias (DCB)) (with respect to the code
+ * type in {@link GnssClock#getReferenceConstellationTypeForIsb())</li>
* </ul>
*
* <p>The value is only available if {@link #hasSatelliteInterSignalBiasNanos()} is {@code
@@ -1654,8 +1666,8 @@
gnssMeasurement.mAutomaticGainControlLevelInDb = parcel.readDouble();
gnssMeasurement.mCodeType = parcel.readString();
gnssMeasurement.mBasebandCn0DbHz = parcel.readDouble();
- gnssMeasurement.mReceiverInterSignalBiasNanos = parcel.readDouble();
- gnssMeasurement.mReceiverInterSignalBiasUncertaintyNanos = parcel.readDouble();
+ gnssMeasurement.mFullInterSignalBiasNanos = parcel.readDouble();
+ gnssMeasurement.mFullInterSignalBiasUncertaintyNanos = parcel.readDouble();
gnssMeasurement.mSatelliteInterSignalBiasNanos = parcel.readDouble();
gnssMeasurement.mSatelliteInterSignalBiasUncertaintyNanos = parcel.readDouble();
@@ -1692,8 +1704,8 @@
parcel.writeDouble(mAutomaticGainControlLevelInDb);
parcel.writeString(mCodeType);
parcel.writeDouble(mBasebandCn0DbHz);
- parcel.writeDouble(mReceiverInterSignalBiasNanos);
- parcel.writeDouble(mReceiverInterSignalBiasUncertaintyNanos);
+ parcel.writeDouble(mFullInterSignalBiasNanos);
+ parcel.writeDouble(mFullInterSignalBiasUncertaintyNanos);
parcel.writeDouble(mSatelliteInterSignalBiasNanos);
parcel.writeDouble(mSatelliteInterSignalBiasUncertaintyNanos);
}
@@ -1778,14 +1790,14 @@
builder.append(String.format(format, "CodeType", mCodeType));
}
- if (hasReceiverInterSignalBiasNanos() || hasReceiverInterSignalBiasUncertaintyNanos()) {
+ if (hasFullInterSignalBiasNanos() || hasFullInterSignalBiasUncertaintyNanos()) {
builder.append(String.format(
formatWithUncertainty,
- "ReceiverInterSignalBiasNs",
- hasReceiverInterSignalBiasNanos() ? mReceiverInterSignalBiasNanos : null,
- "ReceiverInterSignalBiasUncertaintyNs",
- hasReceiverInterSignalBiasUncertaintyNanos()
- ? mReceiverInterSignalBiasUncertaintyNanos : null));
+ "InterSignalBiasNs",
+ hasFullInterSignalBiasNanos() ? mFullInterSignalBiasNanos : null,
+ "InterSignalBiasUncertaintyNs",
+ hasFullInterSignalBiasUncertaintyNanos()
+ ? mFullInterSignalBiasUncertaintyNanos : null));
}
if (hasSatelliteInterSignalBiasNanos() || hasSatelliteInterSignalBiasUncertaintyNanos()) {
@@ -1824,8 +1836,8 @@
resetAutomaticGainControlLevel();
resetCodeType();
resetBasebandCn0DbHz();
- resetReceiverInterSignalBiasNanos();
- resetReceiverInterSignalBiasUncertaintyNanos();
+ resetFullInterSignalBiasNanos();
+ resetFullInterSignalBiasUncertaintyNanos();
resetSatelliteInterSignalBiasNanos();
resetSatelliteInterSignalBiasUncertaintyNanos();
}
diff --git a/media/java/android/media/AudioMetadata.java b/media/java/android/media/AudioMetadata.java
index e67ba59..1a9517c 100644
--- a/media/java/android/media/AudioMetadata.java
+++ b/media/java/android/media/AudioMetadata.java
@@ -41,43 +41,47 @@
private static final String TAG = "AudioMetadata";
/**
- * Key interface for the map.
+ * Key interface for the {@code AudioMetadata} map.
*
- * The presence of this {@code Key} interface on an object allows
- * it to be used to reference metadata in the Audio Framework.
+ * <p>The presence of this {@code Key} interface on an object allows
+ * it to reference metadata in the Audio Framework.</p>
+ *
+ * <p>Vendors are allowed to implement this {@code Key} interface for their debugging or
+ * private application use. To avoid name conflicts, vendor key names should be qualified by
+ * the vendor company name followed by a dot; for example, "vendorCompany.someVolume".</p>
*
* @param <T> type of value associated with {@code Key}.
*/
- // Conceivably metadata keys exposing multiple interfaces
- // could be eligible to work in multiple framework domains.
+ /*
+ * Internal details:
+ * Conceivably metadata keys exposing multiple interfaces
+ * could be eligible to work in multiple framework domains.
+ */
public interface Key<T> {
/**
- * Returns the internal name of the key.
+ * Returns the internal name of the key. The name should be unique in the
+ * {@code AudioMetadata} namespace. Vendors should prefix their keys with
+ * the company name followed by a dot.
*/
@NonNull
String getName();
/**
- * Returns the class type of the associated value.
+ * Returns the class type {@code T} of the associated value. Valid class types for
+ * {@link android.os.Build.VERSION_CODES#R} are
+ * {@code Integer.class}, {@code Long.class}, {@code Float.class}, {@code Double.class},
+ * {@code String.class}.
*/
@NonNull
Class<T> getValueClass();
// TODO: consider adding bool isValid(@NonNull T value)
-
- /**
- * Do not allow non-framework apps to create their own keys
- * by implementing this interface; keep a method hidden.
- *
- * @hide
- */
- boolean isFromFramework();
}
/**
* A read only {@code Map} interface of {@link Key} value pairs.
*
- * Using a {@link Key} interface, look up the corresponding value.
+ * <p>Using a {@link Key} interface, the map looks up the corresponding value.</p>
*/
public interface ReadMap {
/**
@@ -301,12 +305,6 @@
return mType;
}
- // hidden interface method to prevent user class implements the of Key interface.
- @Override
- public boolean isFromFramework() {
- return true;
- }
-
/**
* Return true if the name and the type of two objects are the same.
*/
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index 3a771bb..ad9486c 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -870,16 +870,17 @@
private int getSessionResourceId() throws MediaCasException {
validateInternalStates();
- int[] sessionResourceId = new int[1];
- sessionResourceId[0] = -1;
+ int[] sessionResourceHandle = new int[1];
+ sessionResourceHandle[0] = -1;
if (mTunerResourceManager != null) {
CasSessionRequest casSessionRequest = new CasSessionRequest(mClientId, mCasSystemId);
- if (!mTunerResourceManager.requestCasSession(casSessionRequest, sessionResourceId)) {
- throw new MediaCasException.ResourceBusyException(
+ if (!mTunerResourceManager
+ .requestCasSession(casSessionRequest, sessionResourceHandle)) {
+ throw new MediaCasException.InsufficientResourceException(
"insufficient resource to Open Session");
}
}
- return sessionResourceId[0];
+ return sessionResourceHandle[0];
}
private void addSessionToResourceMap(Session session, int sessionResourceId) {
@@ -905,6 +906,10 @@
* Open a session to descramble one or more streams scrambled by the
* conditional access system.
*
+ * <p>Tuner resource manager (TRM) uses the client priority value to decide whether it is able
+ * to get cas session resource if cas session resources is limited. If the client can't get the
+ * resource, this call returns {@link MediaCasException.InsufficientResourceException }.
+ *
* @return session the newly opened session.
*
* @throws IllegalStateException if the MediaCas instance is not valid.
@@ -930,6 +935,10 @@
* Open a session with usage and scrambling information, so that descrambler can be configured
* to descramble one or more streams scrambled by the conditional access system.
*
+ * <p>Tuner resource manager (TRM) uses the client priority value to decide whether it is able
+ * to get cas session resource if cas session resources is limited. If the client can't get the
+ * resource, this call returns {@link MediaCasException.InsufficientResourceException}.
+ *
* @param sessionUsage used for the created session.
* @param scramblingMode used for the created session.
*
diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java
index 392e8fe..a5da648 100644
--- a/media/java/android/media/audiofx/Visualizer.java
+++ b/media/java/android/media/audiofx/Visualizer.java
@@ -20,9 +20,10 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.Looper;
-import android.os.Message;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
import java.lang.ref.WeakReference;
/**
@@ -158,6 +159,7 @@
/**
* Indicates the state of the Visualizer instance
*/
+ @GuardedBy("mStateLock")
private int mState = STATE_UNINITIALIZED;
/**
* Lock to synchronize access to mState
@@ -166,6 +168,7 @@
/**
* System wide unique Identifier of the visualizer engine used by this Visualizer instance
*/
+ @GuardedBy("mStateLock")
@UnsupportedAppUsage
private int mId;
@@ -176,19 +179,24 @@
/**
* Handler for events coming from the native code
*/
- private NativeEventHandler mNativeEventHandler = null;
+ @GuardedBy("mListenerLock")
+ private Handler mNativeEventHandler = null;
/**
* PCM and FFT capture listener registered by client
*/
+ @GuardedBy("mListenerLock")
private OnDataCaptureListener mCaptureListener = null;
/**
* Server Died listener registered by client
*/
+ @GuardedBy("mListenerLock")
private OnServerDiedListener mServerDiedListener = null;
// accessed by native methods
- private long mNativeVisualizer;
- private long mJniData;
+ private long mNativeVisualizer; // guarded by a static lock in native code
+ private long mJniData; // set in native_setup, _release;
+ // get in native_release, _setEnabled, _setPeriodicCapture
+ // thus, effectively guarded by mStateLock
//--------------------------------------------------------------------------
// Constructor, Finalize
@@ -244,7 +252,9 @@
@Override
protected void finalize() {
- native_finalize();
+ synchronized (mStateLock) {
+ native_finalize();
+ }
}
/**
@@ -601,25 +611,28 @@
*/
public int setDataCaptureListener(OnDataCaptureListener listener,
int rate, boolean waveform, boolean fft) {
- synchronized (mListenerLock) {
- mCaptureListener = listener;
- }
if (listener == null) {
// make sure capture callback is stopped in native code
waveform = false;
fft = false;
}
- int status = native_setPeriodicCapture(rate, waveform, fft);
+ int status;
+ synchronized (mStateLock) {
+ status = native_setPeriodicCapture(rate, waveform, fft);
+ }
if (status == SUCCESS) {
- if ((listener != null) && (mNativeEventHandler == null)) {
- Looper looper;
- if ((looper = Looper.myLooper()) != null) {
- mNativeEventHandler = new NativeEventHandler(this, looper);
- } else if ((looper = Looper.getMainLooper()) != null) {
- mNativeEventHandler = new NativeEventHandler(this, looper);
- } else {
- mNativeEventHandler = null;
- status = ERROR_NO_INIT;
+ synchronized (mListenerLock) {
+ mCaptureListener = listener;
+ if ((listener != null) && (mNativeEventHandler == null)) {
+ Looper looper;
+ if ((looper = Looper.myLooper()) != null) {
+ mNativeEventHandler = new Handler(looper);
+ } else if ((looper = Looper.getMainLooper()) != null) {
+ mNativeEventHandler = new Handler(looper);
+ } else {
+ mNativeEventHandler = null;
+ status = ERROR_NO_INIT;
+ }
}
}
}
@@ -663,112 +676,61 @@
return SUCCESS;
}
- /**
- * Helper class to handle the forwarding of native events to the appropriate listeners
- */
- private class NativeEventHandler extends Handler
- {
- private Visualizer mVisualizer;
-
- public NativeEventHandler(Visualizer v, Looper looper) {
- super(looper);
- mVisualizer = v;
- }
-
- private void handleCaptureMessage(Message msg) {
- OnDataCaptureListener l = null;
- synchronized (mListenerLock) {
- l = mVisualizer.mCaptureListener;
- }
-
- if (l != null) {
- byte[] data = (byte[])msg.obj;
- int samplingRate = msg.arg1;
-
- switch(msg.what) {
- case NATIVE_EVENT_PCM_CAPTURE:
- l.onWaveFormDataCapture(mVisualizer, data, samplingRate);
- break;
- case NATIVE_EVENT_FFT_CAPTURE:
- l.onFftDataCapture(mVisualizer, data, samplingRate);
- break;
- default:
- Log.e(TAG,"Unknown native event in handleCaptureMessge: "+msg.what);
- break;
- }
- }
- }
-
- private void handleServerDiedMessage(Message msg) {
- OnServerDiedListener l = null;
- synchronized (mListenerLock) {
- l = mVisualizer.mServerDiedListener;
- }
-
- if (l != null)
- l.onServerDied();
- }
-
- @Override
- public void handleMessage(Message msg) {
- if (mVisualizer == null) {
- return;
- }
-
- switch(msg.what) {
- case NATIVE_EVENT_PCM_CAPTURE:
- case NATIVE_EVENT_FFT_CAPTURE:
- handleCaptureMessage(msg);
- break;
- case NATIVE_EVENT_SERVER_DIED:
- handleServerDiedMessage(msg);
- break;
- default:
- Log.e(TAG,"Unknown native event: "+msg.what);
- break;
- }
- }
- }
-
//---------------------------------------------------------
// Interface definitions
//--------------------
private static native final void native_init();
+ @GuardedBy("mStateLock")
private native final int native_setup(Object audioeffect_this,
int audioSession,
int[] id,
String opPackageName);
+ @GuardedBy("mStateLock")
private native final void native_finalize();
+ @GuardedBy("mStateLock")
private native final void native_release();
+ @GuardedBy("mStateLock")
private native final int native_setEnabled(boolean enabled);
+ @GuardedBy("mStateLock")
private native final boolean native_getEnabled();
+ @GuardedBy("mStateLock")
private native final int native_setCaptureSize(int size);
+ @GuardedBy("mStateLock")
private native final int native_getCaptureSize();
+ @GuardedBy("mStateLock")
private native final int native_setScalingMode(int mode);
+ @GuardedBy("mStateLock")
private native final int native_getScalingMode();
+ @GuardedBy("mStateLock")
private native final int native_setMeasurementMode(int mode);
+ @GuardedBy("mStateLock")
private native final int native_getMeasurementMode();
+ @GuardedBy("mStateLock")
private native final int native_getSamplingRate();
+ @GuardedBy("mStateLock")
private native final int native_getWaveForm(byte[] waveform);
+ @GuardedBy("mStateLock")
private native final int native_getFft(byte[] fft);
+ @GuardedBy("mStateLock")
private native final int native_getPeakRms(MeasurementPeakRms measurement);
+ @GuardedBy("mStateLock")
private native final int native_setPeriodicCapture(int rate, boolean waveForm, boolean fft);
//---------------------------------------------------------
@@ -776,17 +738,47 @@
//--------------------
@SuppressWarnings("unused")
private static void postEventFromNative(Object effect_ref,
- int what, int arg1, int arg2, Object obj) {
- Visualizer visu = (Visualizer)((WeakReference)effect_ref).get();
- if (visu == null) {
- return;
- }
+ int what, int samplingRate, byte[] data) {
+ final Visualizer visualizer = (Visualizer) ((WeakReference) effect_ref).get();
+ if (visualizer == null) return;
- if (visu.mNativeEventHandler != null) {
- Message m = visu.mNativeEventHandler.obtainMessage(what, arg1, arg2, obj);
- visu.mNativeEventHandler.sendMessage(m);
+ final Handler handler;
+ synchronized (visualizer.mListenerLock) {
+ handler = visualizer.mNativeEventHandler;
}
+ if (handler == null) return;
+ switch (what) {
+ case NATIVE_EVENT_PCM_CAPTURE:
+ case NATIVE_EVENT_FFT_CAPTURE:
+ handler.post(() -> {
+ final OnDataCaptureListener l;
+ synchronized (visualizer.mListenerLock) {
+ l = visualizer.mCaptureListener;
+ }
+ if (l != null) {
+ if (what == NATIVE_EVENT_PCM_CAPTURE) {
+ l.onWaveFormDataCapture(visualizer, data, samplingRate);
+ } else { // what == NATIVE_EVENT_FFT_CAPTURE
+ l.onFftDataCapture(visualizer, data, samplingRate);
+ }
+ }
+ });
+ break;
+ case NATIVE_EVENT_SERVER_DIED:
+ handler.post(() -> {
+ final OnServerDiedListener l;
+ synchronized (visualizer.mListenerLock) {
+ l = visualizer.mServerDiedListener;
+ }
+ if (l != null) {
+ l.onServerDied();
+ }
+ });
+ break;
+ default:
+ Log.e(TAG, "Unknown native event in postEventFromNative: " + what);
+ break;
+ }
}
}
-
diff --git a/media/java/android/media/tv/OWNERS b/media/java/android/media/tv/OWNERS
index 64c0bb5..a891154 100644
--- a/media/java/android/media/tv/OWNERS
+++ b/media/java/android/media/tv/OWNERS
@@ -3,3 +3,7 @@
shubang@google.com
quxiangfang@google.com
+# For android remote service
+per-file ITvRemoteServiceInput.aidl = file:/media/lib/tvremote/OWNERS
+per-file ITvRemoteProvider.aidl = file:/media/lib/tvremote/OWNERS
+
diff --git a/media/java/android/media/tv/tuner/Descrambler.java b/media/java/android/media/tv/tuner/Descrambler.java
index 40add56..975604c 100644
--- a/media/java/android/media/tv/tuner/Descrambler.java
+++ b/media/java/android/media/tv/tuner/Descrambler.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.media.tv.tuner.TunerConstants.Result;
+import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.filter.Filter;
import java.lang.annotation.Retention;
diff --git a/media/java/android/media/tv/tuner/Lnb.java b/media/java/android/media/tv/tuner/Lnb.java
index ea06632..9ce895e 100644
--- a/media/java/android/media/tv/tuner/Lnb.java
+++ b/media/java/android/media/tv/tuner/Lnb.java
@@ -19,11 +19,10 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
import android.hardware.tv.tuner.V1_0.Constants;
-import android.media.tv.tuner.TunerConstants.Result;
+import android.media.tv.tuner.Tuner.Result;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -173,10 +172,8 @@
* @param voltage the power voltage constant the Lnb to use.
* @return result status of the operation.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Result
public int setVoltage(@Voltage int voltage) {
- TunerUtils.checkTunerPermission(mContext);
return nativeSetVoltage(voltage);
}
@@ -186,10 +183,8 @@
* @param tone the tone mode the Lnb to use.
* @return result status of the operation.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Result
public int setTone(@Tone int tone) {
- TunerUtils.checkTunerPermission(mContext);
return nativeSetTone(tone);
}
@@ -199,10 +194,8 @@
* @param position the position the Lnb to use.
* @return result status of the operation.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Result
public int setSatellitePosition(@Position int position) {
- TunerUtils.checkTunerPermission(mContext);
return nativeSetSatellitePosition(position);
}
@@ -216,19 +209,15 @@
*
* @return result status of the operation.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Result
public int sendDiseqcMessage(@NonNull byte[] message) {
- TunerUtils.checkTunerPermission(mContext);
return nativeSendDiseqcMessage(message);
}
/**
* Releases the LNB instance.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public void close() {
- TunerUtils.checkTunerPermission(mContext);
nativeClose();
}
}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 08a33f1..3eb77d5 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -26,7 +26,6 @@
import android.content.Context;
import android.hardware.tv.tuner.V1_0.Constants;
import android.media.tv.TvInputService;
-import android.media.tv.tuner.TunerConstants.Result;
import android.media.tv.tuner.dvr.DvrPlayback;
import android.media.tv.tuner.dvr.DvrRecorder;
import android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener;
@@ -44,12 +43,16 @@
import android.media.tv.tuner.frontend.OnTuneEventListener;
import android.media.tv.tuner.frontend.ScanCallback;
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
+import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
+import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
+import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
import android.media.tv.tunerresourcemanager.TunerResourceManager;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.Message;
+import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -68,6 +71,96 @@
*/
@SystemApi
public class Tuner implements AutoCloseable {
+ /**
+ * Invalid TS packet ID.
+ */
+ public static final int INVALID_TS_PID = Constants.Constant.INVALID_TS_PID;
+ /**
+ * Invalid stream ID.
+ */
+ public static final int INVALID_STREAM_ID = Constants.Constant.INVALID_STREAM_ID;
+ /**
+ * Invalid filter ID.
+ */
+ public static final int INVALID_FILTER_ID = Constants.Constant.INVALID_FILTER_ID;
+ /**
+ * Invalid AV Sync ID.
+ */
+ public static final int INVALID_AV_SYNC_ID = Constants.Constant.INVALID_AV_SYNC_ID;
+ /**
+ * Invalid timestamp.
+ *
+ * <p>Returned by {@link android.media.tv.tuner.filter.TimeFilter#getSourceTime()},
+ * {@link android.media.tv.tuner.filter.TimeFilter#getTimeStamp()}, or
+ * {@link Tuner#getAvSyncTime(int)} when the requested timestamp is not available.
+ *
+ * @see android.media.tv.tuner.filter.TimeFilter#getSourceTime()
+ * @see android.media.tv.tuner.filter.TimeFilter#getTimeStamp()
+ * @see Tuner#getAvSyncTime(int)
+ */
+ public static final long INVALID_TIMESTAMP = -1L;
+
+
+ /** @hide */
+ @IntDef(prefix = "SCAN_TYPE_", value = {SCAN_TYPE_UNDEFINED, SCAN_TYPE_AUTO, SCAN_TYPE_BLIND})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ScanType {}
+ /**
+ * Scan type undefined.
+ */
+ public static final int SCAN_TYPE_UNDEFINED = Constants.FrontendScanType.SCAN_UNDEFINED;
+ /**
+ * Scan type auto.
+ *
+ * <p> Tuner will send {@link android.media.tv.tuner.frontend.ScanCallback#onLocked}
+ */
+ public static final int SCAN_TYPE_AUTO = Constants.FrontendScanType.SCAN_AUTO;
+ /**
+ * Blind scan.
+ *
+ * <p>Frequency range is not specified. The {@link android.media.tv.tuner.Tuner} will scan an
+ * implementation specific range.
+ */
+ public static final int SCAN_TYPE_BLIND = Constants.FrontendScanType.SCAN_BLIND;
+
+
+ /** @hide */
+ @IntDef({RESULT_SUCCESS, RESULT_UNAVAILABLE, RESULT_NOT_INITIALIZED, RESULT_INVALID_STATE,
+ RESULT_INVALID_ARGUMENT, RESULT_OUT_OF_MEMORY, RESULT_UNKNOWN_ERROR})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Result {}
+
+ /**
+ * Operation succeeded.
+ */
+ public static final int RESULT_SUCCESS = Constants.Result.SUCCESS;
+ /**
+ * Operation failed because the corresponding resources are not available.
+ */
+ public static final int RESULT_UNAVAILABLE = Constants.Result.UNAVAILABLE;
+ /**
+ * Operation failed because the corresponding resources are not initialized.
+ */
+ public static final int RESULT_NOT_INITIALIZED = Constants.Result.NOT_INITIALIZED;
+ /**
+ * Operation failed because it's not in a valid state.
+ */
+ public static final int RESULT_INVALID_STATE = Constants.Result.INVALID_STATE;
+ /**
+ * Operation failed because there are invalid arguments.
+ */
+ public static final int RESULT_INVALID_ARGUMENT = Constants.Result.INVALID_ARGUMENT;
+ /**
+ * Memory allocation failed.
+ */
+ public static final int RESULT_OUT_OF_MEMORY = Constants.Result.OUT_OF_MEMORY;
+ /**
+ * Operation failed due to unknown errors.
+ */
+ public static final int RESULT_UNKNOWN_ERROR = Constants.Result.UNKNOWN_ERROR;
+
+
+
private static final String TAG = "MediaTvTuner";
private static final boolean DEBUG = false;
@@ -93,23 +186,27 @@
public static final int DVR_TYPE_PLAYBACK = Constants.DvrType.PLAYBACK;
static {
- System.loadLibrary("media_tv_tuner");
- nativeInit();
+ try {
+ System.loadLibrary("media_tv_tuner");
+ nativeInit();
+ } catch (UnsatisfiedLinkError e) {
+ Log.d(TAG, "tuner JNI library not found!");
+ }
}
private final Context mContext;
private final TunerResourceManager mTunerResourceManager;
private final int mClientId;
- private List<Integer> mFrontendIds;
private Frontend mFrontend;
private EventHandler mHandler;
@Nullable
private FrontendInfo mFrontendInfo;
+ private Integer mFrontendHandle;
+ private int mFrontendType = FrontendSettings.TYPE_UNDEFINED;
- private List<Integer> mLnbIds;
private Lnb mLnb;
- private Integer mLnbId;
+ private Integer mLnbHandle;
@Nullable
private OnTuneEventListener mOnTuneEventListener;
@Nullable
@@ -123,6 +220,8 @@
@Nullable
private Executor mOnResourceLostListenerExecutor;
+ private Integer mDemuxHandle;
+ private Integer mDescramblerHandle;
private final TunerResourceManager.ResourcesReclaimListener mResourceListener =
new TunerResourceManager.ResourcesReclaimListener() {
@@ -160,7 +259,6 @@
* @param executor the executor on which the listener should be invoked.
* @param listener the listener that will be run.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public void setResourceLostListener(@NonNull @CallbackExecutor Executor executor,
@NonNull OnResourceLostListener listener) {
Objects.requireNonNull(executor, "OnResourceLostListener must not be null");
@@ -172,7 +270,6 @@
/**
* Removes the listener for resource lost.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public void clearResourceLostListener() {
mOnResourceLostListener = null;
mOnResourceLostListenerExecutor = null;
@@ -183,9 +280,10 @@
*
* @param tuner the Tuner instance to share frontend resource with.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public void shareFrontendFromTuner(@NonNull Tuner tuner) {
- // TODO: implementation.
+ mTunerResourceManager.shareFrontend(mClientId, tuner.mClientId);
+ mFrontendHandle = tuner.mFrontendHandle;
+ nativeOpenFrontendByHandle(mFrontendHandle);
}
/**
@@ -199,9 +297,8 @@
* @param priority the new priority.
* @param niceValue the nice value.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public void updateResourcePriority(int priority, int niceValue) {
- // TODO: implementation.
+ mTunerResourceManager.updateClientPriority(mClientId, priority, niceValue);
}
private long mNativeContext; // used by native jMediaTuner
@@ -209,10 +306,16 @@
/**
* Releases the Tuner instance.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Override
public void close() {
- // TODO: implementation.
+ if (mFrontendHandle != null) {
+ mTunerResourceManager.releaseFrontend(mFrontendHandle);
+ mFrontendHandle = null;
+ }
+ if (mLnb != null) {
+ mTunerResourceManager.releaseLnb(mLnbHandle);
+ mLnb = null;
+ }
}
/**
@@ -233,7 +336,7 @@
/**
* Native method to open frontend of the given ID.
*/
- private native Frontend nativeOpenFrontendById(int id);
+ private native Frontend nativeOpenFrontendByHandle(int handle);
private native int nativeTune(int type, FrontendSettings settings);
private native int nativeStopTune();
private native int nativeScan(int settingsType, FrontendSettings settings, int scanType);
@@ -250,7 +353,7 @@
private native TimeFilter nativeOpenTimeFilter();
private native List<Integer> nativeGetLnbIds();
- private native Lnb nativeOpenLnbById(int id);
+ private native Lnb nativeOpenLnbByHandle(int handle);
private native Lnb nativeOpenLnbByName(String name);
private native Descrambler nativeOpenDescrambler();
@@ -334,10 +437,8 @@
* @throws SecurityException if the caller does not have appropriate permissions.
* @see #tune(FrontendSettings)
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public void setOnTuneEventListener(@NonNull @CallbackExecutor Executor executor,
@NonNull OnTuneEventListener eventListener) {
- TunerUtils.checkTunerPermission(mContext);
mOnTuneEventListener = eventListener;
mOnTunerEventExecutor = executor;
}
@@ -348,7 +449,6 @@
* @throws SecurityException if the caller does not have appropriate permissions.
* @see #setOnTuneEventListener(Executor, OnTuneEventListener)
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public void clearOnTuneEventListener() {
TunerUtils.checkTunerPermission(mContext);
mOnTuneEventListener = null;
@@ -359,6 +459,10 @@
/**
* Tunes the frontend to using the settings given.
*
+ * <p>Tuner resource manager (TRM) uses the client priority value to decide whether it is able
+ * to get frontend resource. If the client can't get the resource, this call returns {@link
+ * Result#RESULT_UNAVAILABLE}.
+ *
* <p>
* This locks the frontend to a frequency by providing signal
* delivery information. If previous tuning isn't completed, this stop the previous tuning, and
@@ -375,10 +479,10 @@
* @throws SecurityException if the caller does not have appropriate permissions.
* @see #setOnTuneEventListener(Executor, OnTuneEventListener)
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Result
public int tune(@NonNull FrontendSettings settings) {
- TunerUtils.checkTunerPermission(mContext);
+ mFrontendType = settings.getType();
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND);
mFrontendInfo = null;
return nativeTune(settings.getType(), settings);
}
@@ -391,7 +495,6 @@
*
* @return result status of the operation.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Result
public int cancelTuning() {
TunerUtils.checkTunerPermission(mContext);
@@ -409,16 +512,16 @@
* @throws IllegalStateException if {@code scan} is called again before
* {@link #cancelScanning()} is called.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Result
- public int scan(@NonNull FrontendSettings settings, @TunerConstants.ScanType int scanType,
+ public int scan(@NonNull FrontendSettings settings, @ScanType int scanType,
@NonNull @CallbackExecutor Executor executor, @NonNull ScanCallback scanCallback) {
- TunerUtils.checkTunerPermission(mContext);
if (mScanCallback != null || mScanCallbackExecutor != null) {
throw new IllegalStateException(
"Scan already in progress. stopScan must be called before a new scan can be "
+ "started.");
}
+ mFrontendType = settings.getType();
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND);
mScanCallback = scanCallback;
mScanCallbackExecutor = executor;
mFrontendInfo = null;
@@ -436,16 +539,24 @@
*
* @throws SecurityException if the caller does not have appropriate permissions.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Result
public int cancelScanning() {
- TunerUtils.checkTunerPermission(mContext);
int retVal = nativeStopScan();
mScanCallback = null;
mScanCallbackExecutor = null;
return retVal;
}
+ private boolean requestFrontend() {
+ int[] feHandle = new int[1];
+ TunerFrontendRequest request = new TunerFrontendRequest(mClientId, mFrontendType);
+ boolean granted = mTunerResourceManager.requestFrontend(request, feHandle);
+ if (granted) {
+ mFrontendHandle = feHandle[0];
+ }
+ return granted;
+ }
+
/**
* Sets Low-Noise Block downconverter (LNB) for satellite frontend.
*
@@ -468,10 +579,8 @@
*
* @return result status of the operation.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Result
public int setLnaEnabled(boolean enable) {
- TunerUtils.checkTunerPermission(mContext);
return nativeSetLna(enable);
}
@@ -494,11 +603,10 @@
* @param filter the filter instance for the hardware sync ID.
* @return the id of hardware A/V sync.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public int getAvSyncHwId(@NonNull Filter filter) {
- TunerUtils.checkTunerPermission(mContext);
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX);
Integer id = nativeGetAvSyncHwId(filter);
- return id == null ? TunerConstants.INVALID_AV_SYNC_ID : id;
+ return id == null ? INVALID_AV_SYNC_ID : id;
}
/**
@@ -510,11 +618,10 @@
* @param avSyncHwId the hardware id of A/V sync.
* @return the current timestamp of hardware A/V sync.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public long getAvSyncTime(int avSyncHwId) {
- TunerUtils.checkTunerPermission(mContext);
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX);
Long time = nativeGetAvSyncTime(avSyncHwId);
- return time == null ? TunerConstants.TIMESTAMP_UNAVAILABLE : time;
+ return time == null ? INVALID_TIMESTAMP : time;
}
/**
@@ -526,10 +633,9 @@
* @param ciCamId specify CI-CAM Id to connect.
* @return result status of the operation.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Result
public int connectCiCam(int ciCamId) {
- TunerUtils.checkTunerPermission(mContext);
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX);
return nativeConnectCiCam(ciCamId);
}
@@ -540,10 +646,9 @@
*
* @return result status of the operation.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Result
public int disconnectCiCam() {
- TunerUtils.checkTunerPermission(mContext);
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX);
return nativeDisconnectCiCam();
}
@@ -552,10 +657,9 @@
*
* @return The frontend information. {@code null} if the operation failed.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
public FrontendInfo getFrontendInfo() {
- TunerUtils.checkTunerPermission(mContext);
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND);
if (mFrontend == null) {
throw new IllegalStateException("frontend is not initialized");
}
@@ -568,33 +672,14 @@
/**
* Gets Demux capabilities.
*
- * @param context the context of the caller.
* @return A {@link DemuxCapabilities} instance that represents the demux capabilities.
* {@code null} if the operation failed.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
- public static DemuxCapabilities getDemuxCapabilities(@NonNull Context context) {
- TunerUtils.checkTunerPermission(context);
+ public DemuxCapabilities getDemuxCapabilities() {
return nativeGetDemuxCapabilities();
}
- private List<Integer> getFrontendIds() {
- mFrontendIds = nativeGetFrontendIds();
- return mFrontendIds;
- }
-
- private Frontend openFrontendById(int id) {
- if (mFrontendIds == null) {
- mFrontendIds = getFrontendIds();
- }
- if (!mFrontendIds.contains(id)) {
- return null;
- }
- mFrontend = nativeOpenFrontendById(id);
- return mFrontend;
- }
-
private void onFrontendEvent(int eventType) {
if (mOnTunerEventExecutor != null && mOnTuneEventListener != null) {
mOnTunerEventExecutor.execute(() -> mOnTuneEventListener.onTuneEvent(eventType));
@@ -697,12 +782,11 @@
* @param cb the callback to receive notifications from filter.
* @return the opened filter. {@code null} if the operation failed.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
public Filter openFilter(@Type int mainType, @Subtype int subType,
@BytesLong long bufferSize, @CallbackExecutor @Nullable Executor executor,
@Nullable FilterCallback cb) {
- TunerUtils.checkTunerPermission(mContext);
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX);
Filter filter = nativeOpenFilter(
mainType, TunerUtils.getFilterSubtype(mainType, subType), bufferSize);
if (filter != null) {
@@ -726,16 +810,12 @@
* @param cb the callback to receive notifications from LNB.
* @return the opened LNB object. {@code null} if the operation failed.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
public Lnb openLnb(@CallbackExecutor @NonNull Executor executor, @NonNull LnbCallback cb) {
Objects.requireNonNull(executor, "executor must not be null");
Objects.requireNonNull(cb, "LnbCallback must not be null");
- TunerUtils.checkTunerPermission(mContext);
- if (mLnbId == null && !requestLnb()) {
- return null;
- }
- return nativeOpenLnbById(mLnbId);
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_LNB);
+ return nativeOpenLnbByHandle(mLnbHandle);
}
/**
@@ -747,23 +827,22 @@
* @param cb the callback to receive notifications from LNB.
* @return the opened LNB object. {@code null} if the operation failed.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
public Lnb openLnbByName(@NonNull String name, @CallbackExecutor @NonNull Executor executor,
@NonNull LnbCallback cb) {
Objects.requireNonNull(name, "LNB name must not be null");
Objects.requireNonNull(executor, "executor must not be null");
Objects.requireNonNull(cb, "LnbCallback must not be null");
- TunerUtils.checkTunerPermission(mContext);
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_LNB);
return nativeOpenLnbByName(name);
}
private boolean requestLnb() {
- int[] lnbId = new int[1];
+ int[] lnbHandle = new int[1];
TunerLnbRequest request = new TunerLnbRequest(mClientId);
- boolean granted = mTunerResourceManager.requestLnb(request, lnbId);
+ boolean granted = mTunerResourceManager.requestLnb(request, lnbHandle);
if (granted) {
- mLnbId = lnbId[0];
+ mLnbHandle = lnbHandle[0];
}
return granted;
}
@@ -775,25 +854,10 @@
*/
@Nullable
public TimeFilter openTimeFilter() {
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX);
return nativeOpenTimeFilter();
}
- private List<Integer> getLnbIds() {
- mLnbIds = nativeGetLnbIds();
- return mLnbIds;
- }
-
- private Lnb openLnbById(int id) {
- if (mLnbIds == null) {
- mLnbIds = getLnbIds();
- }
- if (!mLnbIds.contains(id)) {
- return null;
- }
- mLnb = nativeOpenLnbById(id);
- return mLnb;
- }
-
private void onLnbEvent(int eventType) {
if (mHandler != null) {
mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_LNB_EVENT, eventType, 0));
@@ -808,7 +872,7 @@
@RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER)
@Nullable
public Descrambler openDescrambler() {
- TunerUtils.checkDescramblerPermission(mContext);
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DESCRAMBLER);
return nativeOpenDescrambler();
}
@@ -822,7 +886,6 @@
* @param l the listener to receive notifications from DVR recorder.
* @return the opened DVR recorder object. {@code null} if the operation failed.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
public DvrRecorder openDvrRecorder(
@BytesLong long bufferSize,
@@ -830,7 +893,7 @@
@NonNull OnRecordStatusChangedListener l) {
Objects.requireNonNull(executor, "executor must not be null");
Objects.requireNonNull(l, "OnRecordStatusChangedListener must not be null");
- TunerUtils.checkTunerPermission(mContext);
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX);
DvrRecorder dvr = nativeOpenDvrRecorder(bufferSize);
return dvr;
}
@@ -845,7 +908,6 @@
* @param l the listener to receive notifications from DVR recorder.
* @return the opened DVR playback object. {@code null} if the operation failed.
*/
- @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
public DvrPlayback openDvrPlayback(
@BytesLong long bufferSize,
@@ -853,8 +915,58 @@
@NonNull OnPlaybackStatusChangedListener l) {
Objects.requireNonNull(executor, "executor must not be null");
Objects.requireNonNull(l, "OnPlaybackStatusChangedListener must not be null");
- TunerUtils.checkTunerPermission(mContext);
+ checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX);
DvrPlayback dvr = nativeOpenDvrPlayback(bufferSize);
return dvr;
}
+
+ private boolean requestDemux() {
+ int[] demuxHandle = new int[1];
+ TunerDemuxRequest request = new TunerDemuxRequest(mClientId);
+ boolean granted = mTunerResourceManager.requestDemux(request, demuxHandle);
+ if (granted) {
+ mDemuxHandle = demuxHandle[0];
+ }
+ return granted;
+ }
+
+ private boolean requestDescrambler() {
+ int[] descramblerHandle = new int[1];
+ TunerDescramblerRequest request = new TunerDescramblerRequest(mClientId);
+ boolean granted = mTunerResourceManager.requestDescrambler(request, descramblerHandle);
+ if (granted) {
+ mDescramblerHandle = descramblerHandle[0];
+ }
+ return granted;
+ }
+
+ private boolean checkResource(int resourceType) {
+ switch (resourceType) {
+ case TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND: {
+ if (mFrontendHandle == null && !requestFrontend()) {
+ return false;
+ }
+ break;
+ }
+ case TunerResourceManager.TUNER_RESOURCE_TYPE_LNB: {
+ if (mLnbHandle == null && !requestLnb()) {
+ return false;
+ }
+ break;
+ }
+ case TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX: {
+ if (mDemuxHandle == null && !requestDemux()) {
+ return false;
+ }
+ break;
+ }
+ case TunerResourceManager.TUNER_RESOURCE_TYPE_DESCRAMBLER: {
+ if (mDescramblerHandle == null && !requestDescrambler()) {
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+ }
}
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
deleted file mode 100644
index 6d89962..0000000
--- a/media/java/android/media/tv/tuner/TunerConstants.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.
- */
-
-package android.media.tv.tuner;
-
-import android.annotation.IntDef;
-import android.annotation.SystemApi;
-import android.hardware.tv.tuner.V1_0.Constants;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Constants for tuner framework.
- *
- * @hide
- */
-@SystemApi
-public final class TunerConstants {
- /**
- * Invalid TS packet ID.
- */
- public static final int INVALID_TS_PID = Constants.Constant.INVALID_TS_PID;
- /**
- * Invalid stream ID.
- */
- public static final int INVALID_STREAM_ID = Constants.Constant.INVALID_STREAM_ID;
- /**
- * Invalid filter ID.
- */
- public static final int INVALID_FILTER_ID = Constants.Constant.INVALID_FILTER_ID;
- /**
- * Invalid AV Sync ID.
- */
- public static final int INVALID_AV_SYNC_ID = Constants.Constant.INVALID_AV_SYNC_ID;
- /**
- * Timestamp is unavailable.
- *
- * <p>Returned by {@link android.media.tv.tuner.filter.TimeFilter#getSourceTime()},
- * {@link android.media.tv.tuner.filter.TimeFilter#getTimeStamp()}, or
- * {@link Tuner#getAvSyncTime(int)} when the requested timestamp is not available.
- *
- * @see android.media.tv.tuner.filter.TimeFilter#getSourceTime()
- * @see android.media.tv.tuner.filter.TimeFilter#getTimeStamp()
- * @see Tuner#getAvSyncTime(int)
- * @hide
- */
- public static final long TIMESTAMP_UNAVAILABLE = -1L;
-
- /** @hide */
- @IntDef(prefix = "SCAN_TYPE_", value = {SCAN_TYPE_UNDEFINED, SCAN_TYPE_AUTO, SCAN_TYPE_BLIND})
- @Retention(RetentionPolicy.SOURCE)
- public @interface ScanType {}
- /**
- * Scan type undefined.
- */
- public static final int SCAN_TYPE_UNDEFINED = Constants.FrontendScanType.SCAN_UNDEFINED;
- /**
- * Scan type auto.
- *
- * <p> Tuner will send {@link android.media.tv.tuner.frontend.ScanCallback#onLocked}
- */
- public static final int SCAN_TYPE_AUTO = Constants.FrontendScanType.SCAN_AUTO;
- /**
- * Blind scan.
- *
- * <p>Frequency range is not specified. The {@link android.media.tv.tuner.Tuner} will scan an
- * implementation specific range.
- */
- public static final int SCAN_TYPE_BLIND = Constants.FrontendScanType.SCAN_BLIND;
-
- /** @hide */
- @IntDef({RESULT_SUCCESS, RESULT_UNAVAILABLE, RESULT_NOT_INITIALIZED, RESULT_INVALID_STATE,
- RESULT_INVALID_ARGUMENT, RESULT_OUT_OF_MEMORY, RESULT_UNKNOWN_ERROR})
- @Retention(RetentionPolicy.SOURCE)
- public @interface Result {}
-
- /**
- * Operation succeeded.
- */
- public static final int RESULT_SUCCESS = Constants.Result.SUCCESS;
- /**
- * Operation failed because the corresponding resources are not available.
- */
- public static final int RESULT_UNAVAILABLE = Constants.Result.UNAVAILABLE;
- /**
- * Operation failed because the corresponding resources are not initialized.
- */
- public static final int RESULT_NOT_INITIALIZED = Constants.Result.NOT_INITIALIZED;
- /**
- * Operation failed because it's not in a valid state.
- */
- public static final int RESULT_INVALID_STATE = Constants.Result.INVALID_STATE;
- /**
- * Operation failed because there are invalid arguments.
- */
- public static final int RESULT_INVALID_ARGUMENT = Constants.Result.INVALID_ARGUMENT;
- /**
- * Memory allocation failed.
- */
- public static final int RESULT_OUT_OF_MEMORY = Constants.Result.OUT_OF_MEMORY;
- /**
- * Operation failed due to unknown errors.
- */
- public static final int RESULT_UNKNOWN_ERROR = Constants.Result.UNKNOWN_ERROR;
-
- private TunerConstants() {
- }
-}
diff --git a/media/java/android/media/tv/tuner/TunerUtils.java b/media/java/android/media/tv/tuner/TunerUtils.java
index 2258ee5..a41b397 100644
--- a/media/java/android/media/tv/tuner/TunerUtils.java
+++ b/media/java/android/media/tv/tuner/TunerUtils.java
@@ -60,6 +60,7 @@
* @throws SecurityException if the caller doesn't have the permission.
*/
public static void checkPermission(Context context, String permission) {
+ // TODO: remove checkPermission methods
if (context.checkCallingOrSelfPermission(permission)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Caller must have " + permission + " permission.");
@@ -171,22 +172,22 @@
*/
@Nullable
public static void throwExceptionForResult(
- @TunerConstants.Result int r, @Nullable String msg) {
+ @Tuner.Result int r, @Nullable String msg) {
if (msg == null) {
msg = "";
}
switch (r) {
- case TunerConstants.RESULT_INVALID_ARGUMENT:
+ case Tuner.RESULT_INVALID_ARGUMENT:
throw new IllegalArgumentException(msg);
- case TunerConstants.RESULT_INVALID_STATE:
+ case Tuner.RESULT_INVALID_STATE:
throw new IllegalStateException(msg);
- case TunerConstants.RESULT_NOT_INITIALIZED:
+ case Tuner.RESULT_NOT_INITIALIZED:
throw new IllegalStateException("Invalid state: not initialized. " + msg);
- case TunerConstants.RESULT_OUT_OF_MEMORY:
+ case Tuner.RESULT_OUT_OF_MEMORY:
throw new OutOfMemoryError(msg);
- case TunerConstants.RESULT_UNAVAILABLE:
+ case Tuner.RESULT_UNAVAILABLE:
throw new IllegalStateException("Invalid state: resource unavailable. " + msg);
- case TunerConstants.RESULT_UNKNOWN_ERROR:
+ case Tuner.RESULT_UNKNOWN_ERROR:
throw new RuntimeException("Unknown error" + msg);
default:
break;
diff --git a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
index 37a016e..0d10d94 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
@@ -21,7 +21,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.hardware.tv.tuner.V1_0.Constants;
-import android.media.tv.tuner.TunerConstants.Result;
+import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.filter.Filter;
import android.os.ParcelFileDescriptor;
diff --git a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
index d06356c..dbda7bb 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
@@ -19,7 +19,7 @@
import android.annotation.BytesLong;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.media.tv.tuner.TunerConstants.Result;
+import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.filter.Filter;
import android.os.ParcelFileDescriptor;
diff --git a/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java
index 8a29442..e40b080 100644
--- a/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/AlpFilterConfiguration.java
@@ -125,8 +125,8 @@
* Builder for {@link AlpFilterConfiguration}.
*/
public static final class Builder {
- private int mPacketType;
- private int mLengthType;
+ private int mPacketType = PACKET_TYPE_IPV4;
+ private int mLengthType = LENGTH_TYPE_UNDEFINED;
private Settings mSettings;
private Builder() {
@@ -136,6 +136,7 @@
* Sets packet type.
*
* <p>The meaning of each packet type value is shown in ATSC A/330:2019 table 5.2.
+ * <p>Default value is {@link #PACKET_TYPE_IPV4}.
*/
@NonNull
public Builder setPacketType(int packetType) {
@@ -144,6 +145,8 @@
}
/**
* Sets length type.
+ *
+ * <p>Default value is {@link #LENGTH_TYPE_UNDEFINED}.
*/
@NonNull
public Builder setLengthType(@LengthType int lengthType) {
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index 4777fe8..8dc0622 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -22,7 +22,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.hardware.tv.tuner.V1_0.Constants;
-import android.media.tv.tuner.TunerConstants.Result;
+import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.TunerUtils;
import java.lang.annotation.Retention;
diff --git a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
index 04f3410..de75a4f 100644
--- a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java
@@ -106,11 +106,11 @@
* Builder for {@link IpFilterConfiguration}.
*/
public static final class Builder {
- private byte[] mSrcIpAddress;
- private byte[] mDstIpAddress;
- private int mSrcPort;
- private int mDstPort;
- private boolean mPassthrough;
+ private byte[] mSrcIpAddress = {0, 0, 0, 0};
+ private byte[] mDstIpAddress = {0, 0, 0, 0};;
+ private int mSrcPort = 0;
+ private int mDstPort = 0;
+ private boolean mPassthrough = false;
private Settings mSettings;
private Builder() {
@@ -118,6 +118,8 @@
/**
* Sets source IP address.
+ *
+ * <p>Default value is 0.0.0.0, an invalid IP address.
*/
@NonNull
public Builder setSrcIpAddress(@NonNull byte[] srcIpAddress) {
@@ -126,6 +128,8 @@
}
/**
* Sets destination IP address.
+ *
+ * <p>Default value is 0.0.0.0, an invalid IP address.
*/
@NonNull
public Builder setDstIpAddress(@NonNull byte[] dstIpAddress) {
@@ -134,6 +138,8 @@
}
/**
* Sets source port.
+ *
+ * <p>Default value is 0.
*/
@NonNull
public Builder setSrcPort(int srcPort) {
@@ -142,6 +148,8 @@
}
/**
* Sets destination port.
+ *
+ * <p>Default value is 0.
*/
@NonNull
public Builder setDstPort(int dstPort) {
@@ -150,6 +158,8 @@
}
/**
* Sets passthrough.
+ *
+ * <p>Default value is {@code false}.
*/
@NonNull
public Builder setPassthrough(boolean passthrough) {
diff --git a/media/java/android/media/tv/tuner/filter/MmtpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/MmtpFilterConfiguration.java
index c0453b4..f19edc9 100644
--- a/media/java/android/media/tv/tuner/filter/MmtpFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/MmtpFilterConfiguration.java
@@ -21,6 +21,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
+import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.TunerUtils;
/**
@@ -67,7 +68,7 @@
* Builder for {@link IpFilterConfiguration}.
*/
public static final class Builder {
- private int mMmtpPid;
+ private int mMmtpPid = Tuner.INVALID_TS_PID;
private Settings mSettings;
private Builder() {
@@ -75,6 +76,8 @@
/**
* Sets MMTP Packet ID.
+ *
+ * <p>Default value is {@link Tuner#INVALID_TS_PID}.
*/
@NonNull
public Builder setMmtpPacketId(int mmtpPid) {
diff --git a/media/java/android/media/tv/tuner/filter/TimeFilter.java b/media/java/android/media/tv/tuner/filter/TimeFilter.java
index 371ccc4..be0a055 100644
--- a/media/java/android/media/tv/tuner/filter/TimeFilter.java
+++ b/media/java/android/media/tv/tuner/filter/TimeFilter.java
@@ -17,8 +17,8 @@
package android.media.tv.tuner.filter;
import android.annotation.SystemApi;
-import android.media.tv.tuner.TunerConstants;
-import android.media.tv.tuner.TunerConstants.Result;
+import android.media.tv.tuner.Tuner;
+import android.media.tv.tuner.Tuner.Result;
import android.media.tv.tuner.TunerUtils;
/**
@@ -35,17 +35,6 @@
@SystemApi
public class TimeFilter implements AutoCloseable {
- /**
- * Timestamp is unavailable.
- *
- * <p>Returned by {@link #getSourceTime()} or {@link #getTimeStamp()} when the requested
- * timestamp is not available.
- *
- * @see #getSourceTime()
- * @see #getTimeStamp()
- */
- public static final long TIMESTAMP_UNAVAILABLE = -1L;
-
private native int nativeSetTimestamp(long timestamp);
private native int nativeClearTimestamp();
@@ -108,12 +97,12 @@
*
* @return current timestamp in the time filter. It's based on the 90KHz counter, and it's
* the same format as PTS (Presentation Time Stamp) defined in ISO/IEC 13818-1:2019. The
- * timestamps may or may not be related to PTS or DTS. Returns {@link #TIMESTAMP_UNAVAILABLE}
- * if the timestamp is never set.
+ * timestamps may or may not be related to PTS or DTS. Returns
+ * {@link Tuner#INVALID_TIMESTAMP} if the timestamp is never set.
*/
public long getTimeStamp() {
if (!mEnable) {
- return TIMESTAMP_UNAVAILABLE;
+ return Tuner.INVALID_TIMESTAMP;
}
return nativeGetTimestamp();
}
@@ -126,11 +115,11 @@
* @return first timestamp of incoming data stream. It's based on the 90KHz counter, and
* it's the same format as PTS (Presentation Time Stamp) defined in ISO/IEC 13818-1:2019.
* The timestamps may or may not be related to PTS or DTS. Returns
- * {@link #TIMESTAMP_UNAVAILABLE} if the timestamp is not available.
+ * {@link Tuner#INVALID_TIMESTAMP} if the timestamp is not available.
*/
public long getSourceTime() {
if (!mEnable) {
- return TIMESTAMP_UNAVAILABLE;
+ return Tuner.INVALID_TIMESTAMP;
}
return nativeGetSourceTime();
}
@@ -144,7 +133,7 @@
@Override
public void close() {
int res = nativeClose();
- if (res != TunerConstants.RESULT_SUCCESS) {
+ if (res != Tuner.RESULT_SUCCESS) {
TunerUtils.throwExceptionForResult(res, "Failed to close time filter.");
}
}
diff --git a/media/java/android/media/tv/tuner/filter/TlvFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/TlvFilterConfiguration.java
index c5191bf..eb1de52 100644
--- a/media/java/android/media/tv/tuner/filter/TlvFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/TlvFilterConfiguration.java
@@ -110,9 +110,9 @@
* Builder for {@link TlvFilterConfiguration}.
*/
public static final class Builder {
- private int mPacketType;
- private boolean mIsCompressedIpPacket;
- private boolean mPassthrough;
+ private int mPacketType = PACKET_TYPE_NULL;
+ private boolean mIsCompressedIpPacket = false;
+ private boolean mPassthrough = false;
private Settings mSettings;
private Builder() {
@@ -122,6 +122,7 @@
* Sets packet type.
*
* <p>The description of each packet type value is shown in ITU-R BT.1869 table 2.
+ * <p>Default value is {@link #PACKET_TYPE_NULL}.
*/
@NonNull
public Builder setPacketType(int packetType) {
@@ -130,6 +131,8 @@
}
/**
* Sets whether the data is compressed IP packet.
+ *
+ * <p>Default value is {@code false}.
*/
@NonNull
public Builder setCompressedIpPacket(boolean isCompressedIpPacket) {
@@ -138,6 +141,8 @@
}
/**
* Sets whether it's passthrough.
+ *
+ * <p>Default value is {@code false}.
*/
@NonNull
public Builder setPassthrough(boolean passthrough) {
diff --git a/media/java/android/media/tv/tuner/filter/TsFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/TsFilterConfiguration.java
index a7140eb..0579269 100644
--- a/media/java/android/media/tv/tuner/filter/TsFilterConfiguration.java
+++ b/media/java/android/media/tv/tuner/filter/TsFilterConfiguration.java
@@ -65,7 +65,7 @@
* Builder for {@link TsFilterConfiguration}.
*/
public static final class Builder {
- private int mTpid;
+ private int mTpid = 0;
private Settings mSettings;
private Builder() {
@@ -74,6 +74,8 @@
/**
* Sets Tag Protocol ID.
*
+ * <p>Default value is 0.
+ *
* @param tpid the Tag Protocol ID.
*/
@NonNull
diff --git a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
index 382cc85..e68585d 100644
--- a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java
@@ -215,14 +215,16 @@
* Builder for {@link AnalogFrontendSettings}.
*/
public static class Builder {
- private int mFrequency;
- private int mSignalType;
- private int mSifStandard;
+ private int mFrequency = 0;
+ private int mSignalType = SIGNAL_TYPE_UNDEFINED;
+ private int mSifStandard = SIF_UNDEFINED;
private Builder() {}
/**
* Sets frequency in Hz.
+ *
+ * <p>Default value is 0.
*/
@NonNull
@IntRange(from = 1)
@@ -233,6 +235,8 @@
/**
* Sets analog signal type.
+ *
+ * <p>Default value is {@link #SIGNAL_TYPE_UNDEFINED}.
*/
@NonNull
public Builder setSignalType(@SignalType int signalType) {
@@ -242,6 +246,8 @@
/**
* Sets Standard Interchange Format (SIF).
+ *
+ * <p>Default value is {@link #SIF_UNDEFINED}.
*/
@NonNull
public Builder setSifStandard(@SifStandard int sifStandard) {
diff --git a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
index 1394716..bf4f3b2 100644
--- a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java
@@ -327,16 +327,18 @@
* Builder for {@link Atsc3FrontendSettings}.
*/
public static class Builder {
- private int mFrequency;
- private int mBandwidth;
- private int mDemodOutputFormat;
- private Atsc3PlpSettings[] mPlpSettings;
+ private int mFrequency = 0;
+ private int mBandwidth = BANDWIDTH_UNDEFINED;
+ private int mDemodOutputFormat = DEMOD_OUTPUT_FORMAT_UNDEFINED;
+ private Atsc3PlpSettings[] mPlpSettings = {};
private Builder() {
}
/**
* Sets frequency in Hz.
+ *
+ * <p>Default value is 0.
*/
@NonNull
@IntRange(from = 1)
@@ -347,6 +349,8 @@
/**
* Sets bandwidth.
+ *
+ * <p>Default value is {@link #BANDWIDTH_UNDEFINED}.
*/
@NonNull
public Builder setBandwidth(int bandwidth) {
@@ -355,6 +359,8 @@
}
/**
* Sets Demod Output Format.
+ *
+ * <p>Default value is {@link #DEMOD_OUTPUT_FORMAT_UNDEFINED}.
*/
@NonNull
public Builder setDemodOutputFormat(@DemodOutputFormat int demodOutputFormat) {
@@ -363,6 +369,8 @@
}
/**
* Sets PLP Settings.
+ *
+ * <p>Default value an empty array.
*/
@NonNull
public Builder setPlpSettings(@NonNull Atsc3PlpSettings[] plpSettings) {
diff --git a/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
index 53352f0..0674f6e 100644
--- a/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/AtscFrontendSettings.java
@@ -93,14 +93,16 @@
* Builder for {@link AtscFrontendSettings}.
*/
public static class Builder {
- private int mFrequency;
- private int mModulation;
+ private int mFrequency = 0;
+ private int mModulation = MODULATION_UNDEFINED;
private Builder() {
}
/**
* Sets frequency in Hz.
+ *
+ * <p>Default value is 0.
*/
@NonNull
@IntRange(from = 1)
@@ -111,6 +113,8 @@
/**
* Sets Modulation.
+ *
+ * <p>Default value is {@link #MODULATION_UNDEFINED}.
*/
@NonNull
public Builder setModulation(@Modulation int modulation) {
diff --git a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
index 6d58570..121de5d 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
@@ -220,19 +220,21 @@
* Builder for {@link DvbcFrontendSettings}.
*/
public static class Builder {
- private int mFrequency;
- private int mModulation;
- private long mInnerFec;
- private int mSymbolRate;
- private int mOuterFec;
- private int mAnnex;
- private int mSpectralInversion;
+ private int mFrequency = 0;
+ private int mModulation = MODULATION_UNDEFINED;
+ private long mInnerFec = FEC_UNDEFINED;
+ private int mSymbolRate = 0;
+ private int mOuterFec = OUTER_FEC_UNDEFINED;
+ private int mAnnex = ANNEX_UNDEFINED;
+ private int mSpectralInversion = SPECTRAL_INVERSION_UNDEFINED;
private Builder() {
}
/**
* Sets frequency in Hz.
+ *
+ * <p>Default value is 0.
*/
@NonNull
@IntRange(from = 1)
@@ -243,6 +245,8 @@
/**
* Sets Modulation.
+ *
+ * <p>Default value is {@link #MODULATION_UNDEFINED}.
*/
@NonNull
public Builder setModulation(@Modulation int modulation) {
@@ -251,6 +255,8 @@
}
/**
* Sets Inner Forward Error Correction.
+ *
+ * <p>Default value is {@link #FEC_UNDEFINED}.
*/
@NonNull
public Builder setInnerFec(@InnerFec long fec) {
@@ -259,6 +265,8 @@
}
/**
* Sets Symbol Rate in symbols per second.
+ *
+ * <p>Default value is 0.
*/
@NonNull
public Builder setSymbolRate(int symbolRate) {
@@ -267,6 +275,8 @@
}
/**
* Sets Outer Forward Error Correction.
+ *
+ * <p>Default value is {@link #OUTER_FEC_UNDEFINED}.
*/
@NonNull
public Builder setOuterFec(@OuterFec int outerFec) {
@@ -275,6 +285,8 @@
}
/**
* Sets Annex.
+ *
+ * <p>Default value is {@link #ANNEX_UNDEFINED}.
*/
@NonNull
public Builder setAnnex(@Annex int annex) {
@@ -283,6 +295,8 @@
}
/**
* Sets Spectral Inversion.
+ *
+ * <p>Default value is {@link #SPECTRAL_INVERSION_UNDEFINED}.
*/
@NonNull
public Builder setSpectralInversion(@SpectralInversion int spectralInversion) {
diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
index 9c45dd1..afc79ab 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java
@@ -24,6 +24,7 @@
import android.annotation.SystemApi;
import android.content.Context;
import android.hardware.tv.tuner.V1_0.Constants;
+import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.TunerUtils;
import java.lang.annotation.Retention;
@@ -305,21 +306,23 @@
* Builder for {@link DvbsFrontendSettings}.
*/
public static class Builder {
- private int mFrequency;
- private int mModulation;
- private DvbsCodeRate mCodeRate;
- private int mSymbolRate;
- private int mRolloff;
- private int mPilot;
- private int mInputStreamId;
- private int mStandard;
- private int mVcmMode;
+ private int mFrequency = 0;
+ private int mModulation = MODULATION_UNDEFINED;
+ private DvbsCodeRate mCodeRate = null;
+ private int mSymbolRate = 0;
+ private int mRolloff = ROLLOFF_UNDEFINED;
+ private int mPilot = PILOT_UNDEFINED;
+ private int mInputStreamId = Tuner.INVALID_STREAM_ID;
+ private int mStandard = STANDARD_AUTO;
+ private int mVcmMode = VCM_MODE_UNDEFINED;
private Builder() {
}
/**
* Sets frequency in Hz.
+ *
+ * <p>Default value is 0.
*/
@NonNull
@IntRange(from = 1)
@@ -330,6 +333,8 @@
/**
* Sets Modulation.
+ *
+ * <p>Default value is {@link #MODULATION_UNDEFINED}.
*/
@NonNull
public Builder setModulation(@Modulation int modulation) {
@@ -338,6 +343,8 @@
}
/**
* Sets Code rate.
+ *
+ * <p>Default value is {@code null}.
*/
@NonNull
public Builder setCodeRate(@Nullable DvbsCodeRate codeRate) {
@@ -346,6 +353,8 @@
}
/**
* Sets Symbol Rate.
+ *
+ * <p>Default value is 0.
*/
@NonNull
public Builder setSymbolRate(int symbolRate) {
@@ -354,6 +363,8 @@
}
/**
* Sets Rolloff.
+ *
+ * <p>Default value is {@link #ROLLOFF_UNDEFINED}.
*/
@NonNull
public Builder setRolloff(@Rolloff int rolloff) {
@@ -362,6 +373,8 @@
}
/**
* Sets Pilot mode.
+ *
+ * <p>Default value is {@link #PILOT_UNDEFINED}.
*/
@NonNull
public Builder setPilot(@Pilot int pilot) {
@@ -370,6 +383,8 @@
}
/**
* Sets Input Stream ID.
+ *
+ * <p>Default value is {@link Tuner#INVALID_STREAM_ID}.
*/
@NonNull
public Builder setInputStreamId(int inputStreamId) {
@@ -378,6 +393,8 @@
}
/**
* Sets Standard.
+ *
+ * <p>Default value is {@link #STANDARD_AUTO}.
*/
@NonNull
public Builder setStandard(@Standard int standard) {
@@ -386,6 +403,8 @@
}
/**
* Sets VCM mode.
+ *
+ * <p>Default value is {@link #VCM_MODE_UNDEFINED}.
*/
@NonNull
public Builder setVcmMode(@VcmMode int vcm) {
diff --git a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
index 4accabb..67a9fdc 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
@@ -508,26 +508,28 @@
* Builder for {@link DvbtFrontendSettings}.
*/
public static class Builder {
- private int mFrequency;
- private int mTransmissionMode;
- private int mBandwidth;
- private int mConstellation;
- private int mHierarchy;
- private int mHpCodeRate;
- private int mLpCodeRate;
- private int mGuardInterval;
- private boolean mIsHighPriority;
- private int mStandard;
- private boolean mIsMiso;
- private int mPlpMode;
- private int mPlpId;
- private int mPlpGroupId;
+ private int mFrequency = 0;
+ private int mTransmissionMode = TRANSMISSION_MODE_UNDEFINED;
+ private int mBandwidth = BANDWIDTH_UNDEFINED;
+ private int mConstellation = CONSTELLATION_UNDEFINED;
+ private int mHierarchy = HIERARCHY_UNDEFINED;
+ private int mHpCodeRate = CODERATE_UNDEFINED;
+ private int mLpCodeRate = CODERATE_UNDEFINED;
+ private int mGuardInterval = GUARD_INTERVAL_UNDEFINED;
+ private boolean mIsHighPriority = false;
+ private int mStandard = STANDARD_AUTO;
+ private boolean mIsMiso = false;
+ private int mPlpMode = PLP_MODE_UNDEFINED;
+ private int mPlpId = 0;
+ private int mPlpGroupId = 0;
private Builder() {
}
/**
* Sets frequency in Hz.
+ *
+ * <p>Default value is 0.
*/
@NonNull
@IntRange(from = 1)
@@ -538,6 +540,8 @@
/**
* Sets Transmission Mode.
+ *
+ * <p>Default value is {@link #TRANSMISSION_MODE_UNDEFINED}.
*/
@NonNull
public Builder setTransmissionMode(@TransmissionMode int transmissionMode) {
@@ -546,6 +550,8 @@
}
/**
* Sets Bandwidth.
+ *
+ * <p>Default value is {@link #BANDWIDTH_UNDEFINED}.
*/
@NonNull
public Builder setBandwidth(@Bandwidth int bandwidth) {
@@ -554,6 +560,8 @@
}
/**
* Sets Constellation.
+ *
+ * <p>Default value is {@link #CONSTELLATION_UNDEFINED}.
*/
@NonNull
public Builder setConstellation(@Constellation int constellation) {
@@ -562,6 +570,8 @@
}
/**
* Sets Hierarchy.
+ *
+ * <p>Default value is {@link #HIERARCHY_UNDEFINED}.
*/
@NonNull
public Builder setHierarchy(@Hierarchy int hierarchy) {
@@ -570,6 +580,8 @@
}
/**
* Sets Code Rate for High Priority level.
+ *
+ * <p>Default value is {@link #CODERATE_UNDEFINED}.
*/
@NonNull
public Builder setHighPriorityCodeRate(@CodeRate int hpCodeRate) {
@@ -578,6 +590,8 @@
}
/**
* Sets Code Rate for Low Priority level.
+ *
+ * <p>Default value is {@link #CODERATE_UNDEFINED}.
*/
@NonNull
public Builder setLowPriorityCodeRate(@CodeRate int lpCodeRate) {
@@ -586,6 +600,8 @@
}
/**
* Sets Guard Interval.
+ *
+ * <p>Default value is {@link #GUARD_INTERVAL_UNDEFINED}.
*/
@NonNull
public Builder setGuardInterval(@GuardInterval int guardInterval) {
@@ -594,6 +610,8 @@
}
/**
* Sets whether it's high priority.
+ *
+ * <p>Default value is {@code false}.
*/
@NonNull
public Builder setHighPriority(boolean isHighPriority) {
@@ -602,6 +620,8 @@
}
/**
* Sets Standard.
+ *
+ * <p>Default value is {@link #STANDARD_AUTO}.
*/
@NonNull
public Builder setStandard(@Standard int standard) {
@@ -610,6 +630,8 @@
}
/**
* Sets whether it's MISO.
+ *
+ * <p>Default value is {@code false}.
*/
@NonNull
public Builder setMiso(boolean isMiso) {
@@ -618,6 +640,8 @@
}
/**
* Sets Physical Layer Pipe (PLP) Mode.
+ *
+ * <p>Default value is {@link #PLP_MODE_UNDEFINED}.
*/
@NonNull
public Builder setPlpMode(@PlpMode int plpMode) {
@@ -626,6 +650,8 @@
}
/**
* Sets Physical Layer Pipe (PLP) ID.
+ *
+ * <p>Default value is 0.
*/
@NonNull
public Builder setPlpId(int plpId) {
@@ -634,6 +660,8 @@
}
/**
* Sets Physical Layer Pipe (PLP) group ID.
+ *
+ * <p>Default value is 0.
*/
@NonNull
public Builder setPlpGroupId(int plpGroupId) {
diff --git a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
index f385379..e0077ca 100644
--- a/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/Isdbs3FrontendSettings.java
@@ -23,6 +23,7 @@
import android.annotation.SystemApi;
import android.content.Context;
import android.hardware.tv.tuner.V1_0.Constants;
+import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.TunerUtils;
import java.lang.annotation.Retention;
@@ -226,19 +227,21 @@
* Builder for {@link Isdbs3FrontendSettings}.
*/
public static class Builder {
- private int mFrequency;
- private int mStreamId;
- private int mStreamIdType;
- private int mModulation;
- private int mCodeRate;
- private int mSymbolRate;
- private int mRolloff;
+ private int mFrequency = 0;
+ private int mStreamId = Tuner.INVALID_STREAM_ID;
+ private int mStreamIdType = IsdbsFrontendSettings.STREAM_ID_TYPE_ID;
+ private int mModulation = MODULATION_UNDEFINED;
+ private int mCodeRate = CODERATE_UNDEFINED;
+ private int mSymbolRate = 0;
+ private int mRolloff = ROLLOFF_UNDEFINED;
private Builder() {
}
/**
* Sets frequency in Hz.
+ *
+ * <p>Default value is 0.
*/
@NonNull
@IntRange(from = 1)
@@ -249,6 +252,8 @@
/**
* Sets Stream ID.
+ *
+ * <p>Default value is {@link Tuner#INVALID_STREAM_ID}.
*/
@NonNull
public Builder setStreamId(int streamId) {
@@ -257,6 +262,8 @@
}
/**
* Sets StreamIdType.
+ *
+ * <p>Default value is {@link IsdbsFrontendSettings#STREAM_ID_TYPE_ID}.
*/
@NonNull
public Builder setStreamIdType(@IsdbsFrontendSettings.StreamIdType int streamIdType) {
@@ -265,6 +272,8 @@
}
/**
* Sets Modulation.
+ *
+ * <p>Default value is {@link #MODULATION_UNDEFINED}.
*/
@NonNull
public Builder setModulation(@Modulation int modulation) {
@@ -273,6 +282,8 @@
}
/**
* Sets Code rate.
+ *
+ * <p>Default value is {@link #CODERATE_UNDEFINED}.
*/
@NonNull
public Builder setCodeRate(@CodeRate int codeRate) {
@@ -281,6 +292,8 @@
}
/**
* Sets Symbol Rate in symbols per second.
+ *
+ * <p>Default value is 0.
*/
@NonNull
public Builder setSymbolRate(int symbolRate) {
@@ -289,6 +302,8 @@
}
/**
* Sets Roll off type.
+ *
+ * <p>Default value is {@link #ROLLOFF_UNDEFINED}.
*/
@NonNull
public Builder setRolloff(@Rolloff int rolloff) {
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
index 4667b9b..8dc591b 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbsFrontendSettings.java
@@ -23,6 +23,7 @@
import android.annotation.SystemApi;
import android.content.Context;
import android.hardware.tv.tuner.V1_0.Constants;
+import android.media.tv.tuner.Tuner;
import android.media.tv.tuner.TunerUtils;
import java.lang.annotation.Retention;
@@ -210,19 +211,21 @@
* Builder for {@link IsdbsFrontendSettings}.
*/
public static class Builder {
- private int mFrequency;
- private int mStreamId;
- private int mStreamIdType;
- private int mModulation;
- private int mCodeRate;
- private int mSymbolRate;
- private int mRolloff;
+ private int mFrequency = 0;
+ private int mStreamId = Tuner.INVALID_STREAM_ID;
+ private int mStreamIdType = STREAM_ID_TYPE_ID;
+ private int mModulation = MODULATION_UNDEFINED;
+ private int mCodeRate = CODERATE_UNDEFINED;
+ private int mSymbolRate = 0;
+ private int mRolloff = ROLLOFF_UNDEFINED;
private Builder() {
}
/**
* Sets frequency in Hz.
+ *
+ * <p>Default value is 0.
*/
@NonNull
@IntRange(from = 1)
@@ -233,6 +236,8 @@
/**
* Sets Stream ID.
+ *
+ * <p>Default value is {@link Tuner#INVALID_STREAM_ID}.
*/
@NonNull
public Builder setStreamId(int streamId) {
@@ -241,6 +246,8 @@
}
/**
* Sets StreamIdType.
+ *
+ * <p>Default value is {@link #STREAM_ID_TYPE_ID}.
*/
@NonNull
public Builder setStreamIdType(@StreamIdType int streamIdType) {
@@ -249,6 +256,8 @@
}
/**
* Sets Modulation.
+ *
+ * <p>Default value is {@link #MODULATION_UNDEFINED}.
*/
@NonNull
public Builder setModulation(@Modulation int modulation) {
@@ -257,6 +266,8 @@
}
/**
* Sets Code rate.
+ *
+ * <p>Default value is {@link #CODERATE_UNDEFINED}.
*/
@NonNull
public Builder setCodeRate(@CodeRate int codeRate) {
@@ -265,6 +276,8 @@
}
/**
* Sets Symbol Rate in symbols per second.
+ *
+ * <p>Default value is 0.
*/
@NonNull
public Builder setSymbolRate(int symbolRate) {
@@ -273,6 +286,8 @@
}
/**
* Sets Roll off type.
+ *
+ * <p>Default value is {@link #ROLLOFF_UNDEFINED}.
*/
@NonNull
public Builder setRolloff(@Rolloff int rolloff) {
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
index b607623..915380e 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
@@ -204,19 +204,21 @@
* Builder for {@link IsdbtFrontendSettings}.
*/
public static class Builder {
- private int mFrequency;
- private int mModulation;
- private int mBandwidth;
- private int mMode;
- private int mCodeRate;
- private int mGuardInterval;
- private int mServiceAreaId;
+ private int mFrequency = 0;
+ private int mModulation = MODULATION_UNDEFINED;
+ private int mBandwidth = BANDWIDTH_UNDEFINED;
+ private int mMode = MODE_UNDEFINED;
+ private int mCodeRate = DvbtFrontendSettings.CODERATE_UNDEFINED;
+ private int mGuardInterval = DvbtFrontendSettings.GUARD_INTERVAL_UNDEFINED;
+ private int mServiceAreaId = 0;
private Builder() {
}
/**
* Sets frequency in Hz.
+ *
+ * <p>Default value is 0.
*/
@NonNull
@IntRange(from = 1)
@@ -227,6 +229,8 @@
/**
* Sets Modulation.
+ *
+ * <p>Default value is {@link #MODULATION_UNDEFINED}.
*/
@NonNull
public Builder setModulation(@Modulation int modulation) {
@@ -235,6 +239,8 @@
}
/**
* Sets Bandwidth.
+ *
+ * <p>Default value is {@link #BANDWIDTH_UNDEFINED}.
*/
@NonNull
public Builder setBandwidth(@Bandwidth int bandwidth) {
@@ -243,6 +249,8 @@
}
/**
* Sets ISDBT mode.
+ *
+ * <p>Default value is {@link #MODE_UNDEFINED}.
*/
@NonNull
public Builder setMode(@Mode int mode) {
@@ -251,14 +259,18 @@
}
/**
* Sets Code rate.
+ *
+ * <p>Default value is {@link DvbtFrontendSettings#CODERATE_UNDEFINED}.
*/
@NonNull
- public Builder setCodeRate(@CodeRate int codeRate) {
+ public Builder setCodeRate(@DvbtFrontendSettings.CodeRate int codeRate) {
mCodeRate = codeRate;
return this;
}
/**
* Sets Guard Interval.
+ *
+ * <p>Default value is {@link DvbtFrontendSettings#GUARD_INTERVAL_UNDEFINED}.
*/
@NonNull
public Builder setGuardInterval(@DvbtFrontendSettings.GuardInterval int guardInterval) {
@@ -267,6 +279,8 @@
}
/**
* Sets Service Area ID.
+ *
+ * <p>Default value is 0.
*/
@NonNull
public Builder setServiceAreaId(int serviceAreaId) {
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
index 9dddcd4..63a71e2 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
+++ b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
@@ -17,6 +17,7 @@
package android.media.tv.tunerresourcemanager;
import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresFeature;
@@ -27,6 +28,8 @@
import android.os.RemoteException;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
/**
@@ -61,6 +64,24 @@
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
public static final int INVALID_RESOURCE_HANDLE = -1;
+ /**
+ * Tuner resource type to help generate resource handle
+ */
+ @IntDef({
+ TUNER_RESOURCE_TYPE_FRONTEND,
+ TUNER_RESOURCE_TYPE_DEMUX,
+ TUNER_RESOURCE_TYPE_DESCRAMBLER,
+ TUNER_RESOURCE_TYPE_LNB,
+ TUNER_RESOURCE_TYPE_CAS_SESSION,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TunerResourceType {}
+
+ public static final int TUNER_RESOURCE_TYPE_FRONTEND = 0;
+ public static final int TUNER_RESOURCE_TYPE_DEMUX = 1;
+ public static final int TUNER_RESOURCE_TYPE_DESCRAMBLER = 2;
+ public static final int TUNER_RESOURCE_TYPE_LNB = 3;
+ public static final int TUNER_RESOURCE_TYPE_CAS_SESSION = 4;
private final ITunerResourceManager mService;
private final int mUserId;
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index a37c9e5..bbeb451 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -1410,6 +1410,10 @@
return (IDescrambler *)env->GetLongField(descrambler, gFields.descramblerContext);
}
+static uint32_t getResourceIdFromHandle(jint handle) {
+ return (handle & 0x00ff0000) >> 16;
+}
+
static DemuxPid getDemuxPid(int pidType, int pid) {
DemuxPid demuxPid;
if ((int)pidType == 1) {
@@ -1968,8 +1972,10 @@
return tuner->getFrontendIds();
}
-static jobject android_media_tv_Tuner_open_frontend_by_id(JNIEnv *env, jobject thiz, jint id) {
+static jobject android_media_tv_Tuner_open_frontend_by_handle(
+ JNIEnv *env, jobject thiz, jint handle) {
sp<JTuner> tuner = getTuner(env, thiz);
+ uint32_t id = getResourceIdFromHandle(handle);
return tuner->openFrontendById(id);
}
@@ -2045,8 +2051,9 @@
return tuner->getLnbIds();
}
-static jobject android_media_tv_Tuner_open_lnb_by_id(JNIEnv *env, jobject thiz, jint id) {
+static jobject android_media_tv_Tuner_open_lnb_by_handle(JNIEnv *env, jobject thiz, jint handle) {
sp<JTuner> tuner = getTuner(env, thiz);
+ uint32_t id = getResourceIdFromHandle(handle);
return tuner->openLnbById(id);
}
@@ -2924,8 +2931,8 @@
{ "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup },
{ "nativeGetFrontendIds", "()Ljava/util/List;",
(void *)android_media_tv_Tuner_get_frontend_ids },
- { "nativeOpenFrontendById", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
- (void *)android_media_tv_Tuner_open_frontend_by_id },
+ { "nativeOpenFrontendByHandle", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
+ (void *)android_media_tv_Tuner_open_frontend_by_handle },
{ "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I",
(void *)android_media_tv_Tuner_tune },
{ "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },
@@ -2950,8 +2957,8 @@
(void *)android_media_tv_Tuner_open_time_filter },
{ "nativeGetLnbIds", "()Ljava/util/List;",
(void *)android_media_tv_Tuner_get_lnb_ids },
- { "nativeOpenLnbById", "(I)Landroid/media/tv/tuner/Lnb;",
- (void *)android_media_tv_Tuner_open_lnb_by_id },
+ { "nativeOpenLnbByHandle", "(I)Landroid/media/tv/tuner/Lnb;",
+ (void *)android_media_tv_Tuner_open_lnb_by_handle },
{ "nativeOpenLnbByName", "(Ljava/lang/String;)Landroid/media/tv/tuner/Lnb;",
(void *)android_media_tv_Tuner_open_lnb_by_name },
{ "nativeOpenDescrambler", "()Landroid/media/tv/tuner/Descrambler;",
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 1362433..f9a77f4 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -196,7 +196,6 @@
callbackInfo->visualizer_ref,
NATIVE_EVENT_PCM_CAPTURE,
samplingrate,
- 0,
jArray);
}
}
@@ -217,7 +216,6 @@
callbackInfo->visualizer_ref,
NATIVE_EVENT_FFT_CAPTURE,
samplingrate,
- 0,
jArray);
}
}
@@ -286,7 +284,7 @@
// Get the postEvent method
fields.midPostNativeEvent = env->GetStaticMethodID(
fields.clazzEffect,
- "postEventFromNative", "(Ljava/lang/Object;IIILjava/lang/Object;)V");
+ "postEventFromNative", "(Ljava/lang/Object;II[B)V");
if (fields.midPostNativeEvent == NULL) {
ALOGE("Can't find Visualizer.%s", "postEventFromNative");
return;
@@ -343,7 +341,7 @@
fields.midPostNativeEvent,
callbackInfo->visualizer_ref,
NATIVE_EVENT_SERVER_DIED,
- 0, 0, NULL);
+ 0, NULL);
}
}
diff --git a/mms/java/android/telephony/MmsManager.java b/mms/java/android/telephony/MmsManager.java
index f07cd5e..6e47741 100644
--- a/mms/java/android/telephony/MmsManager.java
+++ b/mms/java/android/telephony/MmsManager.java
@@ -32,6 +32,7 @@
/**
* Manages MMS operations such as sending multimedia messages.
* Get this object by calling Context#getSystemService(Context#MMS_SERVICE).
+ * @hide
*/
@SystemService(Context.MMS_SERVICE)
public class MmsManager {
diff --git a/packages/CarSystemUI/proguard.flags b/packages/CarSystemUI/proguard.flags
index a81c7e0..66cbf26 100644
--- a/packages/CarSystemUI/proguard.flags
+++ b/packages/CarSystemUI/proguard.flags
@@ -1,3 +1,4 @@
-keep class com.android.systemui.CarSystemUIFactory
+-keep class com.android.car.notification.headsup.animationhelper.**
-include ../SystemUI/proguard.flags
diff --git a/packages/CarSystemUI/res/drawable/headsup_scrim_bottom.xml b/packages/CarSystemUI/res/drawable/headsup_scrim_bottom.xml
new file mode 100644
index 0000000..1724ef0
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/headsup_scrim_bottom.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <gradient
+ android:startColor="@android:color/black"
+ android:endColor="@android:color/transparent"
+ android:angle="90" />
+</shape>
diff --git a/packages/CarSystemUI/res/layout/headsup_container_bottom.xml b/packages/CarSystemUI/res/layout/headsup_container_bottom.xml
new file mode 100644
index 0000000..caf1677
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/headsup_container_bottom.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/notification_headsup"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <androidx.constraintlayout.widget.Guideline
+ android:id="@+id/gradient_edge"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ app:layout_constraintGuide_begin="@dimen/headsup_scrim_height"/>
+
+ <View
+ android:id="@+id/scrim"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:background="@drawable/headsup_scrim_bottom"
+ app:layout_constraintBottom_toBottomOf="@+id/gradient_edge"
+ app:layout_constraintTop_toTopOf="parent"/>
+
+ <FrameLayout
+ android:id="@+id/headsup_content"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/headsup_notification_top_margin"
+ app:layout_constraintEnd_toStartOf="parent"
+ app:layout_constraintStart_toEndOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index aaa65de..2077e77 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -34,6 +34,13 @@
<!-- Whether heads-up notifications should be shown when shade is open. -->
<bool name="config_enableHeadsUpNotificationWhenNotificationShadeOpen">true</bool>
+ <!-- Whether heads-up notifications should be shown on the bottom. If false, heads-up
+ notifications will be shown pushed to the top of their parent container. If true, they will
+ be shown pushed to the bottom of their parent container. If true, then should override
+ config_headsUpNotificationAnimationHelper to use a different AnimationHelper, such as
+ com.android.car.notification.headsup.animationhelper.
+ CarHeadsUpNotificationBottomAnimationHelper. -->
+ <bool name="config_showHeadsUpNotificationOnBottom">false</bool>
<bool name="config_hideNavWhenKeyguardBouncerShown">true</bool>
<bool name="config_enablePersistentDockedActivity">false</bool>
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 8292d30..14d5bd5 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -27,9 +27,11 @@
import com.android.systemui.dagger.SystemUIRootComponent;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerImpl;
+import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.EnhancedEstimatesImpl;
+import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsImplementation;
import com.android.systemui.stackdivider.DividerModule;
@@ -107,6 +109,10 @@
BatteryControllerImpl controllerImpl);
@Binds
+ @Singleton
+ public abstract QSFactory provideQSFactory(QSFactoryImpl qsFactoryImpl);
+
+ @Binds
abstract DockManager bindDockManager(DockManagerImpl dockManager);
@Binds
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/CarHeadsUpNotificationSystemContainer.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/CarHeadsUpNotificationSystemContainer.java
index 689d2d5..53e5d9f 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/notification/CarHeadsUpNotificationSystemContainer.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/CarHeadsUpNotificationSystemContainer.java
@@ -60,6 +60,8 @@
mCarDeviceProvisionedController = deviceProvisionedController;
mCarStatusBarLazy = carStatusBarLazy;
+ boolean showOnBottom = resources.getBoolean(R.bool.config_showHeadsUpNotificationOnBottom);
+
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT,
@@ -68,11 +70,13 @@
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.TRANSLUCENT);
- lp.gravity = Gravity.TOP;
+ lp.gravity = showOnBottom ? Gravity.BOTTOM : Gravity.TOP;
lp.setTitle("HeadsUpNotification");
- mWindow = (ViewGroup) LayoutInflater.from(context)
- .inflate(R.layout.headsup_container, null, false);
+ int layoutId = showOnBottom
+ ? R.layout.headsup_container_bottom
+ : R.layout.headsup_container;
+ mWindow = (ViewGroup) LayoutInflater.from(context).inflate(layoutId, null, false);
windowManager.addView(mWindow, lp);
mWindow.setVisibility(View.INVISIBLE);
mHeadsUpContentFrame = mWindow.findViewById(R.id.headsup_content);
diff --git a/packages/SettingsLib/res/drawable/ic_media_group_device.xml b/packages/SettingsLib/res/drawable/ic_media_group_device.xml
new file mode 100644
index 0000000..ba5e651
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_media_group_device.xml
@@ -0,0 +1,32 @@
+<!--
+ 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
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal">
+ <path
+ android:pathData="M18.2,1L9.8,1C8.81,1 8,1.81 8,2.8v14.4c0,0.99 0.81,1.79 1.8,1.79l8.4,0.01c0.99,0 1.8,-0.81 1.8,-1.8L20,2.8c0,-0.99 -0.81,-1.8 -1.8,-1.8zM14,3c1.1,0 2,0.89 2,2s-0.9,2 -2,2 -2,-0.89 -2,-2 0.9,-2 2,-2zM14,16.5c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4z"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M14,12.5m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"
+ android:fillColor="#000000"/>
+ <path
+ android:pathData="M6,5H4v16c0,1.1 0.89,2 2,2h10v-2H6V5z"
+ android:fillColor="#000000"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 00f6bcb..a797066 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1039,7 +1039,7 @@
<!-- Title for the accessibility preference to configure display color space correction. [CHAR LIMIT=NONE] -->
<string name="accessibility_display_daltonizer_preference_title">Color correction</string>
<!-- Subtitle for the accessibility preference to configure display color space correction. [CHAR LIMIT=NONE] -->
- <string name="accessibility_display_daltonizer_preference_subtitle">Color correction helps the device display more accurate colors. Color correction may be helpful for people with colorblindness.</string>
+ <string name="accessibility_display_daltonizer_preference_subtitle"><![CDATA[Color correction allows you to adjust how colors are displayed on your device]]></string>
<!-- Summary shown for color space correction preference when its value is overridden by another preference [CHAR LIMIT=35] -->
<string name="daltonizer_type_overridden">Overridden by <xliff:g id="title" example="Simulate color space">%1$s</xliff:g></string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
index b725ba5..85fa988 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
@@ -15,11 +15,17 @@
*/
package com.android.settingslib.media;
+import static android.media.MediaRoute2Info.TYPE_GROUP;
+import static android.media.MediaRoute2Info.TYPE_REMOTE_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_REMOTE_TV;
+
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
+import androidx.annotation.VisibleForTesting;
+
import com.android.settingslib.R;
import com.android.settingslib.bluetooth.BluetoothUtils;
@@ -51,7 +57,23 @@
public Drawable getIcon() {
//TODO(b/120669861): Return remote device icon uri once api is ready.
return BluetoothUtils.buildBtRainbowDrawable(mContext,
- mContext.getDrawable(R.drawable.ic_media_device), getId().hashCode());
+ mContext.getDrawable(getDrawableResId()), getId().hashCode());
+ }
+
+ @VisibleForTesting
+ int getDrawableResId() {
+ int resId;
+ switch (mRouteInfo.getType()) {
+ case TYPE_GROUP:
+ resId = R.drawable.ic_media_group_device;
+ break;
+ case TYPE_REMOTE_TV:
+ case TYPE_REMOTE_SPEAKER:
+ default:
+ resId = R.drawable.ic_media_device;
+ break;
+ }
+ return resId;
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
index 166fbaa..af88723 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -15,11 +15,17 @@
*/
package com.android.settingslib.media;
+import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
+import androidx.annotation.VisibleForTesting;
+
import com.android.settingslib.R;
import com.android.settingslib.bluetooth.BluetoothUtils;
@@ -43,7 +49,18 @@
@Override
public String getName() {
- return mContext.getString(R.string.media_transfer_this_device_name);
+ CharSequence name;
+ switch (mRouteInfo.getType()) {
+ case TYPE_WIRED_HEADSET:
+ case TYPE_WIRED_HEADPHONES:
+ name = mRouteInfo.getName();
+ break;
+ case TYPE_BUILTIN_SPEAKER:
+ default:
+ name = mContext.getString(R.string.media_transfer_this_device_name);
+ break;
+ }
+ return name.toString();
}
@Override
@@ -54,7 +71,23 @@
@Override
public Drawable getIcon() {
return BluetoothUtils.buildBtRainbowDrawable(mContext,
- mContext.getDrawable(R.drawable.ic_smartphone), getId().hashCode());
+ mContext.getDrawable(getDrawableResId()), getId().hashCode());
+ }
+
+ @VisibleForTesting
+ int getDrawableResId() {
+ int resId;
+ switch (mRouteInfo.getType()) {
+ case TYPE_WIRED_HEADSET:
+ case TYPE_WIRED_HEADPHONES:
+ resId = com.android.internal.R.drawable.ic_bt_headphones_a2dp;
+ break;
+ case TYPE_BUILTIN_SPEAKER:
+ default:
+ resId = R.drawable.ic_smartphone;
+ break;
+ }
+ return resId;
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
index e351615..dad82ee 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
@@ -63,7 +63,7 @@
}
public UidDetailProvider(Context context) {
- mContext = context.getApplicationContext();
+ mContext = context;
mUidDetailCache = new SparseArray<UidDetail>();
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java
index 77a67c2..685c834 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaDeviceTest.java
@@ -16,6 +16,10 @@
package com.android.settingslib.media;
+import static android.media.MediaRoute2Info.TYPE_GROUP;
+import static android.media.MediaRoute2Info.TYPE_REMOTE_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_REMOTE_TV;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
@@ -86,4 +90,19 @@
assertThat(mInfoMediaDevice.getId()).isEqualTo(TEST_ID);
}
+
+ @Test
+ public void getDrawableResId_returnCorrectResId() {
+ when(mRouteInfo.getType()).thenReturn(TYPE_REMOTE_TV);
+
+ assertThat(mInfoMediaDevice.getDrawableResId()).isEqualTo(R.drawable.ic_media_device);
+
+ when(mRouteInfo.getType()).thenReturn(TYPE_REMOTE_SPEAKER);
+
+ assertThat(mInfoMediaDevice.getDrawableResId()).isEqualTo(R.drawable.ic_media_device);
+
+ when(mRouteInfo.getType()).thenReturn(TYPE_GROUP);
+
+ assertThat(mInfoMediaDevice.getDrawableResId()).isEqualTo(R.drawable.ic_media_group_device);
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java
index db984fb..4c5cd96 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/PhoneMediaDeviceTest.java
@@ -16,15 +16,23 @@
package com.android.settingslib.media;
+import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
import android.content.Context;
+import android.media.MediaRoute2Info;
import com.android.settingslib.R;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@@ -32,6 +40,9 @@
@RunWith(RobolectricTestRunner.class)
public class PhoneMediaDeviceTest {
+ @Mock
+ private MediaRoute2Info mInfo;
+
private Context mContext;
private PhoneMediaDevice mPhoneMediaDevice;
@@ -41,7 +52,7 @@
mContext = RuntimeEnvironment.application;
mPhoneMediaDevice =
- new PhoneMediaDevice(mContext, null, null, null);
+ new PhoneMediaDevice(mContext, null, mInfo, null);
}
@Test
@@ -58,4 +69,42 @@
assertThat(mPhoneMediaDevice.getSummary()).isEmpty();
}
+
+ @Test
+ public void getDrawableResId_returnCorrectResId() {
+ when(mInfo.getType()).thenReturn(TYPE_WIRED_HEADPHONES);
+
+ assertThat(mPhoneMediaDevice.getDrawableResId())
+ .isEqualTo(com.android.internal.R.drawable.ic_bt_headphones_a2dp);
+
+ when(mInfo.getType()).thenReturn(TYPE_WIRED_HEADSET);
+
+ assertThat(mPhoneMediaDevice.getDrawableResId())
+ .isEqualTo(com.android.internal.R.drawable.ic_bt_headphones_a2dp);
+
+ when(mInfo.getType()).thenReturn(TYPE_BUILTIN_SPEAKER);
+
+ assertThat(mPhoneMediaDevice.getDrawableResId()).isEqualTo(R.drawable.ic_smartphone);
+ }
+
+ @Test
+ public void getName_returnCorrectName() {
+ final String deviceName = "test_name";
+
+ when(mInfo.getType()).thenReturn(TYPE_WIRED_HEADPHONES);
+ when(mInfo.getName()).thenReturn(deviceName);
+
+ assertThat(mPhoneMediaDevice.getName())
+ .isEqualTo(deviceName);
+
+ when(mInfo.getType()).thenReturn(TYPE_WIRED_HEADSET);
+
+ assertThat(mPhoneMediaDevice.getName())
+ .isEqualTo(deviceName);
+
+ when(mInfo.getType()).thenReturn(TYPE_BUILTIN_SPEAKER);
+
+ assertThat(mPhoneMediaDevice.getName())
+ .isEqualTo(mContext.getString(R.string.media_transfer_this_device_name));
+ }
}
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 610165a..24cc3c9 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -199,7 +199,6 @@
Settings.Global.CERT_PIN_UPDATE_CONTENT_URL,
Settings.Global.CERT_PIN_UPDATE_METADATA_URL,
Settings.Global.COMPATIBILITY_MODE,
- Settings.Global.COMMON_CRITERIA_MODE,
Settings.Global.CONNECTIVITY_CHANGE_DELAY,
Settings.Global.CONNECTIVITY_METRICS_BUFFER_SIZE,
Settings.Global.CONNECTIVITY_SAMPLING_INTERVAL_IN_SECONDS,
@@ -356,6 +355,7 @@
Settings.Global.NETSTATS_POLL_INTERVAL,
Settings.Global.NETSTATS_SAMPLE_ENABLED,
Settings.Global.NETSTATS_AUGMENT_ENABLED,
+ Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED,
Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE,
Settings.Global.NETSTATS_UID_BUCKET_DURATION,
Settings.Global.NETSTATS_UID_DELETE_AGE,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 8f859b2..8105114 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -278,6 +278,9 @@
<!-- Permission needed to modify settings overrideable by restore in CTS tests -->
<uses-permission android:name="android.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE" />
+ <!-- Permission required for testing system audio effect APIs. -->
+ <uses-permission android:name="android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS"/>
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/res/layout/controls_no_favorites.xml b/packages/SystemUI/res/layout/controls_no_favorites.xml
index 8074efd..74fc167 100644
--- a/packages/SystemUI/res/layout/controls_no_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_no_favorites.xml
@@ -40,14 +40,20 @@
android:paddingBottom="8dp" />
<TextView
+ style="@style/TextAppearance.ControlSetup.Title"
android:id="@+id/controls_title"
android:text="@string/quick_controls_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:singleLine="true"
- android:layout_gravity="center"
- android:textSize="25sp"
- android:textColor="@*android:color/foreground_material_dark"
- android:fontFamily="@*android:string/config_headlineFontFamily" />
+ android:layout_gravity="center" />
+
+ <TextView
+ style="@style/TextAppearance.ControlSetup.Subtitle"
+ android:id="@+id/controls_subtitle"
+ android:visibility="gone"
+ android:layout_marginTop="12dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center" />
</LinearLayout>
</merge>
diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml
index a76f961..d506e7e 100644
--- a/packages/SystemUI/res/layout/global_screenshot.xml
+++ b/packages/SystemUI/res/layout/global_screenshot.xml
@@ -58,13 +58,15 @@
android:elevation="@dimen/screenshot_preview_elevation"
android:visibility="gone"
android:background="@drawable/screenshot_rounded_corners"
- android:adjustViewBounds="true"/>
+ android:adjustViewBounds="true"
+ android:contentDescription="@string/screenshot_preview_description"/>
<FrameLayout
android:id="@+id/global_screenshot_dismiss_button"
android:layout_width="@dimen/screenshot_dismiss_button_tappable_size"
android:layout_height="@dimen/screenshot_dismiss_button_tappable_size"
android:elevation="7dp"
- android:visibility="gone">
+ android:visibility="gone"
+ android:contentDescription="@string/screenshot_dismiss_ui_description">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
index 44c409e..b5822c8 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
@@ -35,7 +35,34 @@
android:forceHasOverlappingRendering="false"
android:clipChildren="false"
>
- <include layout="@layout/status_bar_notification_section_header_contents"/>
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="start|center_vertical"
+ android:layout_weight="1">
+
+ <TextView
+ style="@style/TextAppearance.NotificationSectionHeaderButton"
+ android:id="@+id/header_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:forceHasOverlappingRendering="false"
+ android:text="@string/notification_section_header_gentle"
+ />
+
+ </FrameLayout>
+ <ImageView
+ android:id="@+id/btn_clear_all"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:src="@drawable/status_bar_notification_section_header_clear_btn"
+ android:contentDescription="@string/accessibility_notification_section_header_gentle_clear_all"
+ android:scaleType="center"
+ android:tint="?attr/wallpaperTextColor"
+ android:tintMode="src_in"
+ android:visibility="gone"
+ android:forceHasOverlappingRendering="false"
+ />
</LinearLayout>
</com.android.systemui.statusbar.notification.stack.SectionHeaderView>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml b/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml
deleted file mode 100644
index 3b9c44d..0000000
--- a/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml
+++ /dev/null
@@ -1,47 +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
- -->
-
-<!-- Used by both status_bar_notification_header and SectionHeaderView -->
-<merge xmlns:android="http://schemas.android.com/apk/res/android" >
- <FrameLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="start|center_vertical"
- android:layout_weight="1">
-
- <TextView
- style="@style/TextAppearance.NotificationSectionHeaderButton"
- android:id="@+id/header_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:forceHasOverlappingRendering="false"
- android:text="@string/notification_section_header_gentle"
- />
-
- </FrameLayout>
- <ImageView
- android:id="@+id/btn_clear_all"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:src="@drawable/status_bar_notification_section_header_clear_btn"
- android:contentDescription="@string/accessibility_notification_section_header_gentle_clear_all"
- android:scaleType="center"
- android:tint="?attr/wallpaperTextColor"
- android:tintMode="src_in"
- android:visibility="gone"
- android:forceHasOverlappingRendering="false"
- />
-</merge>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 82224df..4d6b759 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -117,7 +117,7 @@
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
<string name="quick_settings_tiles_stock" translatable="false">
- wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,screenrecord
+ wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,screenrecord,reverse
</string>
<!-- The tiles to display in QuickSettings -->
@@ -532,4 +532,8 @@
<!-- Respect drawable/rounded.xml intrinsic size for multiple radius corner path customization -->
<bool name="config_roundedCornerMultipleRadius">false</bool>
+ <!-- Controls can query a preferred application for limited number of suggested controls.
+ This config value should contain the package name of that preferred application.
+ -->
+ <string translatable="false" name="config_controlsPreferredPackage"></string>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 3543073..cb08840 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -233,6 +233,10 @@
<!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] -->
<string name="screenshot_failed_to_capture_text">Taking screenshots isn\'t allowed by the app or
your organization</string>
+ <!-- Content description indicating that tapping a button will dismiss the screenshots UI [CHAR LIMIT=NONE] -->
+ <string name="screenshot_dismiss_ui_description">Dismiss screenshot</string>
+ <!-- Content description indicating that tapping will open an app to view/edit the screenshot. [CHAR LIMIT=NONE] -->
+ <string name="screenshot_preview_description">Open screenshot</string>
<!-- Notification title displayed for screen recording [CHAR LIMIT=50]-->
<string name="screenrecord_name">Screen Recorder</string>
@@ -2653,4 +2657,8 @@
<!-- Tooltip to show in management screen when there are multiple structures [CHAR_LIMIT=50] -->
<string name="controls_structure_tooltip">Swipe to see other structures</string>
+
+ <!-- Message to tell the user to wait while systemui attempts to load a set of
+ recommended controls [CHAR_LIMIT=30] -->
+ <string name="controls_seeding_in_progress">Loading recommendations</string>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 20b88a1..1283fe0 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -699,6 +699,20 @@
<item name="*android:colorPopupBackground">@color/control_list_popup_background</item>
</style>
+ <style name="TextAppearance.ControlSetup">
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ <item name="android:textColor">@color/control_primary_text</item>
+ <item name="android:singleLine">true</item>
+ </style>
+
+ <style name="TextAppearance.ControlSetup.Title">
+ <item name="android:textSize">25sp</item>
+ </style>
+
+ <style name="TextAppearance.ControlSetup.Subtitle">
+ <item name="android:textSize">16sp</item>
+ </style>
+
<style name="Theme.ControlsRequestDialog" parent="@style/Theme.SystemUI.MediaProjectionAlertDialog"/>
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 431c451..90df124 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -2740,6 +2740,8 @@
mBroadcastDispatcher.unregisterReceiver(mBroadcastReceiver);
mBroadcastDispatcher.unregisterReceiver(mBroadcastAllReceiver);
+
+ mHandler.removeCallbacksAndMessages(null);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index a8a3cae..5f004a6 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -122,7 +122,7 @@
protected int mRoundedDefaultBottom;
@VisibleForTesting
protected View[] mOverlays;
- private DisplayCutoutView[] mCutoutViews;
+ private DisplayCutoutView[] mCutoutViews = new DisplayCutoutView[BOUNDS_POSITION_LENGTH];
private float mDensity;
private WindowManager mWindowManager;
private int mRotation;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index b63ba6f..7ee162e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -89,6 +89,9 @@
private static final int SPRING_AFTER_FLING_STIFFNESS = 750;
private static final float SPRING_AFTER_FLING_DAMPING_RATIO = 0.85f;
+ /** Sentinel value for unset position value. */
+ private static final float UNSET = -Float.MIN_VALUE;
+
/**
* Minimum fling velocity required to trigger moving the stack from one side of the screen to
* the other.
@@ -133,7 +136,7 @@
* The Y position of the stack before the IME became visible, or {@link Float#MIN_VALUE} if the
* IME is not visible or the user moved the stack since the IME became visible.
*/
- private float mPreImeY = Float.MIN_VALUE;
+ private float mPreImeY = UNSET;
/**
* Animations on the stack position itself, which would have been started in
@@ -263,7 +266,7 @@
// If we manually move the bubbles with the IME open, clear the return point since we don't
// want the stack to snap away from the new position.
- mPreImeY = Float.MIN_VALUE;
+ mPreImeY = UNSET;
moveFirstBubbleWithStackFollowing(DynamicAnimation.TRANSLATION_X, x);
moveFirstBubbleWithStackFollowing(DynamicAnimation.TRANSLATION_Y, y);
@@ -512,26 +515,27 @@
* Animates the stack either away from the newly visible IME, or back to its original position
* due to the IME going away.
*
- * @return The destination Y value of the stack due to the IME movement.
+ * @return The destination Y value of the stack due to the IME movement (or the current position
+ * of the stack if it's not moving).
*/
public float animateForImeVisibility(boolean imeVisible) {
final float maxBubbleY = getAllowableStackPositionRegion().bottom;
- float destinationY = Float.MIN_VALUE;
+ float destinationY = UNSET;
if (imeVisible) {
// Stack is lower than it should be and overlaps the now-visible IME.
- if (mStackPosition.y > maxBubbleY && mPreImeY == Float.MIN_VALUE) {
+ if (mStackPosition.y > maxBubbleY && mPreImeY == UNSET) {
mPreImeY = mStackPosition.y;
destinationY = maxBubbleY;
}
} else {
- if (mPreImeY > Float.MIN_VALUE) {
+ if (mPreImeY != UNSET) {
destinationY = mPreImeY;
- mPreImeY = Float.MIN_VALUE;
+ mPreImeY = UNSET;
}
}
- if (destinationY > Float.MIN_VALUE) {
+ if (destinationY != UNSET) {
springFirstBubbleWithStackFollowing(
DynamicAnimation.TRANSLATION_Y,
getSpringForce(DynamicAnimation.TRANSLATION_Y, /* view */ null)
@@ -542,7 +546,7 @@
notifyFloatingCoordinatorStackAnimatingTo(mStackPosition.x, destinationY);
}
- return destinationY;
+ return destinationY != UNSET ? destinationY : mStackPosition.y;
}
/**
@@ -595,7 +599,7 @@
mLayout.getHeight()
- mBubbleSize
- mBubblePaddingTop
- - (mImeHeight > Float.MIN_VALUE ? mImeHeight + mBubblePaddingTop : 0f)
+ - (mImeHeight != UNSET ? mImeHeight + mBubblePaddingTop : 0f)
- Math.max(
insets.getStableInsetBottom(),
insets.getDisplayCutout() != null
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
index c5af436..d4d4d2a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
@@ -43,6 +43,14 @@
fun bindAndLoad(component: ComponentName, callback: LoadCallback): Runnable
/**
+ * Request bind to a service and load a limited number of suggested controls.
+ *
+ * @param component The [ComponentName] of the service to bind
+ * @param callback a callback to return the loaded controls to (or an error).
+ */
+ fun bindAndLoadSuggested(component: ComponentName, callback: LoadCallback)
+
+ /**
* Request to bind to the given service.
*
* @param component The [ComponentName] of the service to bind
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
index f8d4a39..5d03fc5 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -44,6 +44,8 @@
companion object {
private const val TAG = "ControlsBindingControllerImpl"
+ private const val MAX_CONTROLS_REQUEST = 100000L
+ private const val SUGGESTED_CONTROLS_REQUEST = 4L
}
private var currentUser = UserHandle.of(ActivityManager.getCurrentUser())
@@ -97,24 +99,37 @@
component: ComponentName,
callback: ControlsBindingController.LoadCallback
): Runnable {
- val subscriber = LoadSubscriber(callback)
+ val subscriber = LoadSubscriber(callback, MAX_CONTROLS_REQUEST)
retrieveLifecycleManager(component).maybeBindAndLoad(subscriber)
return subscriber.loadCancel()
}
+ override fun bindAndLoadSuggested(
+ component: ComponentName,
+ callback: ControlsBindingController.LoadCallback
+ ) {
+ val subscriber = LoadSubscriber(callback, SUGGESTED_CONTROLS_REQUEST)
+ retrieveLifecycleManager(component).maybeBindAndLoadSuggested(subscriber)
+ }
+
override fun subscribe(structureInfo: StructureInfo) {
// make sure this has happened. only allow one active subscription
unsubscribe()
- statefulControlSubscriber = null
val provider = retrieveLifecycleManager(structureInfo.componentName)
- val scs = StatefulControlSubscriber(lazyController.get(), provider, backgroundExecutor)
+ val scs = StatefulControlSubscriber(
+ lazyController.get(),
+ provider,
+ backgroundExecutor,
+ MAX_CONTROLS_REQUEST
+ )
statefulControlSubscriber = scs
provider.maybeBindAndSubscribe(structureInfo.controls.map { it.controlId }, scs)
}
override fun unsubscribe() {
statefulControlSubscriber?.cancel()
+ statefulControlSubscriber = null
}
override fun action(
@@ -201,10 +216,11 @@
private inner class OnSubscribeRunnable(
token: IBinder,
- val subscription: IControlsSubscription
+ val subscription: IControlsSubscription,
+ val requestLimit: Long
) : CallbackRunnable(token) {
override fun doRun() {
- provider?.startSubscription(subscription)
+ provider?.startSubscription(subscription, requestLimit)
}
}
@@ -234,7 +250,8 @@
}
private inner class LoadSubscriber(
- val callback: ControlsBindingController.LoadCallback
+ val callback: ControlsBindingController.LoadCallback,
+ val requestLimit: Long
) : IControlsSubscriber.Stub() {
val loadedControls = ArrayList<Control>()
var hasError = false
@@ -246,7 +263,7 @@
override fun onSubscribe(token: IBinder, subs: IControlsSubscription) {
_loadCancelInternal = subs::cancel
- backgroundExecutor.execute(OnSubscribeRunnable(token, subs))
+ backgroundExecutor.execute(OnSubscribeRunnable(token, subs, requestLimit))
}
override fun onNext(token: IBinder, c: Control) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
index 9e0d26c..ae75dd4 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -114,6 +114,25 @@
// FAVORITE MANAGEMENT
/**
+ * Send a request to seed favorites into the persisted XML file
+ *
+ * @param componentName the component to seed controls from
+ * @param callback true if the favorites were persisted
+ */
+ fun seedFavoritesForComponent(
+ componentName: ComponentName,
+ callback: Consumer<Boolean>
+ )
+
+ /**
+ * Callback to be informed when the seeding process has finished
+ *
+ * @param callback consumer accepts true if successful
+ * @return true if seeding is in progress and the callback was added
+ */
+ fun addSeedingFavoritesCallback(callback: Consumer<Boolean>): Boolean
+
+ /**
* Get all the favorites.
*
* @return a list of the structures that have at least one favorited control
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index 9cb902f..2e34ea5 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -31,6 +31,7 @@
import android.provider.Settings
import android.service.controls.Control
import android.service.controls.actions.ControlAction
+import android.util.ArrayMap
import android.util.Log
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.Dumpable
@@ -74,6 +75,9 @@
private var loadCanceller: Runnable? = null
+ private var seedingInProgress = false
+ private val seedingCallbacks = mutableListOf<Consumer<Boolean>>()
+
private var currentUser = UserHandle.of(ActivityManager.getCurrentUser())
override val currentUserId
get() = currentUser.identifier
@@ -280,6 +284,84 @@
)
}
+ override fun addSeedingFavoritesCallback(callback: Consumer<Boolean>): Boolean {
+ if (!seedingInProgress) return false
+ executor.execute {
+ // status may have changed by this point, so check again and inform the
+ // caller if necessary
+ if (seedingInProgress) seedingCallbacks.add(callback)
+ else callback.accept(false)
+ }
+ return true
+ }
+
+ override fun seedFavoritesForComponent(
+ componentName: ComponentName,
+ callback: Consumer<Boolean>
+ ) {
+ Log.i(TAG, "Beginning request to seed favorites for: $componentName")
+ if (!confirmAvailability()) {
+ if (userChanging) {
+ // Try again later, userChanging should not last forever. If so, we have bigger
+ // problems. This will return a runnable that allows to cancel the delayed version,
+ // it will not be able to cancel the load if
+ executor.executeDelayed(
+ { seedFavoritesForComponent(componentName, callback) },
+ USER_CHANGE_RETRY_DELAY,
+ TimeUnit.MILLISECONDS
+ )
+ } else {
+ callback.accept(false)
+ }
+ return
+ }
+ seedingInProgress = true
+ bindingController.bindAndLoadSuggested(
+ componentName,
+ object : ControlsBindingController.LoadCallback {
+ override fun accept(controls: List<Control>) {
+ executor.execute {
+ val structureToControls =
+ ArrayMap<CharSequence, MutableList<ControlInfo>>()
+
+ controls.forEach {
+ val structure = it.structure ?: ""
+ val list = structureToControls.get(structure)
+ ?: mutableListOf<ControlInfo>()
+ list.add(ControlInfo(it.controlId, it.title, it.deviceType))
+ structureToControls.put(structure, list)
+ }
+
+ structureToControls.forEach {
+ (s, cs) -> Favorites.replaceControls(
+ StructureInfo(componentName, s, cs))
+ }
+
+ persistenceWrapper.storeFavorites(Favorites.getAllStructures())
+ callback.accept(true)
+ endSeedingCall(true)
+ }
+ }
+
+ override fun error(message: String) {
+ Log.e(TAG, "Unable to seed favorites: $message")
+ executor.execute {
+ callback.accept(false)
+ endSeedingCall(false)
+ }
+ }
+ }
+ )
+ }
+
+ private fun endSeedingCall(state: Boolean) {
+ seedingInProgress = false
+ seedingCallbacks.forEach {
+ it.accept(state)
+ }
+ seedingCallbacks.clear()
+ }
+
override fun cancelLoad() {
loadCanceller?.let {
executor.execute(it)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index 4918bd7..209d056 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -66,22 +66,17 @@
@GuardedBy("subscriptions")
private val subscriptions = mutableListOf<IControlsSubscription>()
private var requiresBound = false
- @GuardedBy("queuedMessages")
- private val queuedMessages: MutableSet<Message> = ArraySet()
+ @GuardedBy("queuedServiceMethods")
+ private val queuedServiceMethods: MutableSet<ServiceMethod> = ArraySet()
private var wrapper: ServiceWrapper? = null
private var bindTryCount = 0
private val TAG = javaClass.simpleName
private var onLoadCanceller: Runnable? = null
companion object {
- private const val MSG_LOAD = 0
- private const val MSG_SUBSCRIBE = 1
- private const val MSG_ACTION = 2
- private const val MSG_UNBIND = 3
private const val BIND_RETRY_DELAY = 1000L // ms
private const val LOAD_TIMEOUT_SECONDS = 30L // seconds
private const val MAX_BIND_RETRIES = 5
- private const val MAX_CONTROLS_REQUEST = 100000L
private const val DEBUG = true
private val BIND_FLAGS = Context.BIND_AUTO_CREATE or Context.BIND_FOREGROUND_SERVICE or
Context.BIND_WAIVE_PRIORITY
@@ -130,7 +125,7 @@
try {
service.linkToDeath(this@ControlsProviderLifecycleManager, 0)
} catch (_: RemoteException) {}
- handlePendingMessages()
+ handlePendingServiceMethods()
}
override fun onServiceDisconnected(name: ComponentName?) {
@@ -140,29 +135,14 @@
}
}
- private fun handlePendingMessages() {
- val queue = synchronized(queuedMessages) {
- ArraySet(queuedMessages).also {
- queuedMessages.clear()
+ private fun handlePendingServiceMethods() {
+ val queue = synchronized(queuedServiceMethods) {
+ ArraySet(queuedServiceMethods).also {
+ queuedServiceMethods.clear()
}
}
- if (Message.Unbind in queue) {
- bindService(false)
- return
- }
-
- queue.filter { it is Message.Load }.forEach {
- val msg = it as Message.Load
- load(msg.subscriber)
- }
-
- queue.filter { it is Message.Subscribe }.forEach {
- val msg = it as Message.Subscribe
- subscribe(msg.list, msg.subscriber)
- }
- queue.filter { it is Message.Action }.forEach {
- val msg = it as Message.Action
- action(msg.id, msg.action)
+ queue.forEach {
+ it.run()
}
}
@@ -177,33 +157,17 @@
}
}
- private fun queueMessage(message: Message) {
- synchronized(queuedMessages) {
- queuedMessages.add(message)
+ private fun queueServiceMethod(sm: ServiceMethod) {
+ synchronized(queuedServiceMethods) {
+ queuedServiceMethods.add(sm)
}
}
- private fun unqueueMessageType(type: Int) {
- synchronized(queuedMessages) {
- queuedMessages.removeIf { it.type == type }
- }
- }
-
- private fun load(subscriber: IControlsSubscriber.Stub) {
- if (DEBUG) {
- Log.d(TAG, "load $componentName")
- }
- if (!(wrapper?.load(subscriber) ?: false)) {
- queueMessage(Message.Load(subscriber))
- binderDied()
- }
- }
-
- private inline fun invokeOrQueue(f: () -> Unit, msg: Message) {
+ private fun invokeOrQueue(sm: ServiceMethod) {
wrapper?.run {
- f()
+ sm.run()
} ?: run {
- queueMessage(msg)
+ queueServiceMethod(sm)
bindService(true)
}
}
@@ -217,7 +181,6 @@
* @param subscriber the subscriber that manages coordination for loading controls
*/
fun maybeBindAndLoad(subscriber: IControlsSubscriber.Stub) {
- unqueueMessageType(MSG_UNBIND)
onLoadCanceller = executor.executeDelayed({
// Didn't receive a response in time, log and send back error
Log.d(TAG, "Timeout waiting onLoad for $componentName")
@@ -225,7 +188,26 @@
unbindService()
}, LOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS)
- invokeOrQueue({ load(subscriber) }, Message.Load(subscriber))
+ invokeOrQueue(Load(subscriber))
+ }
+
+ /**
+ * Request a call to [IControlsProvider.loadSuggested].
+ *
+ * If the service is not bound, the call will be queued and the service will be bound first.
+ * The service will be unbound after the controls are returned or the call times out.
+ *
+ * @param subscriber the subscriber that manages coordination for loading controls
+ */
+ fun maybeBindAndLoadSuggested(subscriber: IControlsSubscriber.Stub) {
+ onLoadCanceller = executor.executeDelayed({
+ // Didn't receive a response in time, log and send back error
+ Log.d(TAG, "Timeout waiting onLoadSuggested for $componentName")
+ subscriber.onError(token, "Timeout waiting onLoadSuggested")
+ unbindService()
+ }, LOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS)
+
+ invokeOrQueue(Suggest(subscriber))
}
fun cancelLoadTimeout() {
@@ -240,23 +222,8 @@
*
* @param controlIds a list of the ids of controls to send status back.
*/
- fun maybeBindAndSubscribe(controlIds: List<String>, subscriber: IControlsSubscriber) {
- invokeOrQueue(
- { subscribe(controlIds, subscriber) },
- Message.Subscribe(controlIds, subscriber)
- )
- }
-
- private fun subscribe(controlIds: List<String>, subscriber: IControlsSubscriber) {
- if (DEBUG) {
- Log.d(TAG, "subscribe $componentName - $controlIds")
- }
-
- if (!(wrapper?.subscribe(controlIds, subscriber) ?: false)) {
- queueMessage(Message.Subscribe(controlIds, subscriber))
- binderDied()
- }
- }
+ fun maybeBindAndSubscribe(controlIds: List<String>, subscriber: IControlsSubscriber) =
+ invokeOrQueue(Subscribe(controlIds, subscriber))
/**
* Request a call to [ControlsProviderService.performControlAction].
@@ -266,19 +233,8 @@
* @param controlId the id of the [Control] the action is performed on
* @param action the action performed
*/
- fun maybeBindAndSendAction(controlId: String, action: ControlAction) {
- invokeOrQueue({ action(controlId, action) }, Message.Action(controlId, action))
- }
-
- private fun action(controlId: String, action: ControlAction) {
- if (DEBUG) {
- Log.d(TAG, "onAction $componentName - $controlId")
- }
- if (!(wrapper?.action(controlId, action, actionCallbackService) ?: false)) {
- queueMessage(Message.Action(controlId, action))
- binderDied()
- }
- }
+ fun maybeBindAndSendAction(controlId: String, action: ControlAction) =
+ invokeOrQueue(Action(controlId, action))
/**
* Starts the subscription to the [ControlsProviderService] and requests status of controls.
@@ -286,14 +242,14 @@
* @param subscription the subscription to use to request controls
* @see maybeBindAndLoad
*/
- fun startSubscription(subscription: IControlsSubscription) {
+ fun startSubscription(subscription: IControlsSubscription, requestLimit: Long) {
if (DEBUG) {
Log.d(TAG, "startSubscription: $subscription")
}
synchronized(subscriptions) {
subscriptions.add(subscription)
}
- wrapper?.request(subscription, MAX_CONTROLS_REQUEST)
+ wrapper?.request(subscription, requestLimit)
}
/**
@@ -316,7 +272,6 @@
* Request bind to the service.
*/
fun bindService() {
- unqueueMessageType(MSG_UNBIND)
bindService(true)
}
@@ -350,21 +305,55 @@
}
/**
- * Messages for the internal queue.
+ * Service methods that can be queued or invoked, and are retryable for failure scenarios
*/
- sealed class Message {
- abstract val type: Int
- class Load(val subscriber: IControlsSubscriber.Stub) : Message() {
- override val type = MSG_LOAD
+ abstract inner class ServiceMethod {
+ fun run() {
+ if (!callWrapper()) {
+ queueServiceMethod(this)
+ binderDied()
+ }
}
- object Unbind : Message() {
- override val type = MSG_UNBIND
+
+ internal abstract fun callWrapper(): Boolean
+ }
+
+ inner class Load(val subscriber: IControlsSubscriber.Stub) : ServiceMethod() {
+ override fun callWrapper(): Boolean {
+ if (DEBUG) {
+ Log.d(TAG, "load $componentName")
+ }
+ return wrapper?.load(subscriber) ?: false
}
- class Subscribe(val list: List<String>, val subscriber: IControlsSubscriber) : Message() {
- override val type = MSG_SUBSCRIBE
+ }
+
+ inner class Suggest(val subscriber: IControlsSubscriber.Stub) : ServiceMethod() {
+ override fun callWrapper(): Boolean {
+ if (DEBUG) {
+ Log.d(TAG, "suggest $componentName")
+ }
+ return wrapper?.loadSuggested(subscriber) ?: false
}
- class Action(val id: String, val action: ControlAction) : Message() {
- override val type = MSG_ACTION
+ }
+ inner class Subscribe(
+ val list: List<String>,
+ val subscriber: IControlsSubscriber
+ ) : ServiceMethod() {
+ override fun callWrapper(): Boolean {
+ if (DEBUG) {
+ Log.d(TAG, "subscribe $componentName - $list")
+ }
+
+ return wrapper?.subscribe(list, subscriber) ?: false
+ }
+ }
+
+ inner class Action(val id: String, val action: ControlAction) : ServiceMethod() {
+ override fun callWrapper(): Boolean {
+ if (DEBUG) {
+ Log.d(TAG, "onAction $componentName - $id")
+ }
+ return wrapper?.action(id, action, actionCallbackService) ?: false
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
index b2afd3c..2c717f5 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
@@ -50,6 +50,12 @@
}
}
+ fun loadSuggested(subscriber: IControlsSubscriber): Boolean {
+ return callThroughService {
+ service.loadSuggested(subscriber)
+ }
+ }
+
fun subscribe(controlIds: List<String>, subscriber: IControlsSubscriber): Boolean {
return callThroughService {
service.subscribe(controlIds, subscriber)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/StatefulControlSubscriber.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/StatefulControlSubscriber.kt
index a371aa6..e3eabff 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/StatefulControlSubscriber.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/StatefulControlSubscriber.kt
@@ -31,7 +31,8 @@
class StatefulControlSubscriber(
private val controller: ControlsController,
private val provider: ControlsProviderLifecycleManager,
- private val bgExecutor: DelayableExecutor
+ private val bgExecutor: DelayableExecutor,
+ private val requestLimit: Long
) : IControlsSubscriber.Stub() {
private var subscriptionOpen = false
private var subscription: IControlsSubscription? = null
@@ -50,7 +51,7 @@
run(token) {
subscriptionOpen = true
subscription = subs
- provider.startSubscription(subs)
+ provider.startSubscription(subs, requestLimit)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
index a7fc2ac8..74a6c87 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
@@ -55,7 +55,7 @@
private lateinit var control: Control
private var dialog: Dialog? = null
private val callback = object : ControlsListingController.ControlsListingCallback {
- override fun onServicesUpdated(candidates: List<ControlsServiceInfo>) {}
+ override fun onServicesUpdated(serviceInfos: List<ControlsServiceInfo>) {}
}
private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 138cd47..ffae4653 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -52,6 +52,7 @@
import dagger.Lazy
import java.text.Collator
+import java.util.function.Consumer
import javax.inject.Inject
import javax.inject.Singleton
@@ -89,6 +90,7 @@
private var popup: ListPopupWindow? = null
private var activeDialog: Dialog? = null
private val addControlsItem: SelectionItem
+ private var hidden = true
init {
val addDrawable = context.getDrawable(R.drawable.ic_add).apply {
@@ -134,11 +136,15 @@
override fun show(parent: ViewGroup) {
Log.d(ControlsUiController.TAG, "show()")
this.parent = parent
+ hidden = false
allStructures = controlsController.get().getFavorites()
selectedStructure = loadPreference(allStructures)
- if (selectedStructure.controls.isEmpty() && allStructures.size <= 1) {
+ val cb = Consumer<Boolean> { _ -> reload(parent) }
+ if (controlsController.get().addSeedingFavoritesCallback(cb)) {
+ listingCallback = createCallback(::showSeedingView)
+ } else if (selectedStructure.controls.isEmpty() && allStructures.size <= 1) {
// only show initial view if there are really no favorites across any structure
listingCallback = createCallback(::showInitialSetupView)
} else {
@@ -154,6 +160,20 @@
controlsListingController.get().addCallback(listingCallback)
}
+ private fun reload(parent: ViewGroup) {
+ if (hidden) return
+ show(parent)
+ }
+
+ private fun showSeedingView(items: List<SelectionItem>) {
+ parent.removeAllViews()
+
+ val inflater = LayoutInflater.from(context)
+ inflater.inflate(R.layout.controls_no_favorites, parent, true)
+ val subtitle = parent.requireViewById<TextView>(R.id.controls_subtitle)
+ subtitle.setVisibility(View.VISIBLE)
+ }
+
private fun showInitialSetupView(items: List<SelectionItem>) {
parent.removeAllViews()
@@ -320,13 +340,14 @@
selectedStructure = newSelection
updatePreferences(selectedStructure)
controlsListingController.get().removeCallback(listingCallback)
- show(parent)
+ reload(parent)
}
}
}
override fun hide() {
Log.d(ControlsUiController.TAG, "hide()")
+ hidden = true
popup?.dismiss()
activeDialog?.dismiss()
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 956b4aa..8c572fe 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -26,9 +26,11 @@
import com.android.keyguard.KeyguardViewController;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerImpl;
+import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.EnhancedEstimatesImpl;
+import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsImplementation;
import com.android.systemui.stackdivider.DividerModule;
@@ -85,6 +87,10 @@
BatteryControllerImpl controllerImpl);
@Binds
+ @Singleton
+ public abstract QSFactory provideQSFactory(QSFactoryImpl qsFactoryImpl);
+
+ @Binds
abstract DockManager bindDockManager(DockManagerImpl dockManager);
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index b99d765..73539f9 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -31,11 +31,13 @@
import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.SharedPreferences;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -92,6 +94,8 @@
import com.android.systemui.MultiListLayout.MultiListAdapter;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.controls.ControlsServiceInfo;
+import com.android.systemui.controls.controller.ControlsController;
import com.android.systemui.controls.management.ControlsListingController;
import com.android.systemui.controls.ui.ControlsUiController;
import com.android.systemui.dagger.qualifiers.Background;
@@ -148,6 +152,9 @@
private static final String GLOBAL_ACTION_KEY_EMERGENCY = "emergency";
private static final String GLOBAL_ACTION_KEY_SCREENSHOT = "screenshot";
+ private static final String PREFS_CONTROLS_SEEDING_COMPLETED = "ControlsSeedingCompleted";
+ private static final String PREFS_CONTROLS_FILE = "controls_prefs";
+
private final Context mContext;
private final GlobalActionsManager mWindowManagerFuncs;
private final AudioManager mAudioManager;
@@ -215,7 +222,8 @@
NotificationShadeWindowController notificationShadeWindowController,
ControlsUiController controlsUiController, IWindowManager iWindowManager,
@Background Executor backgroundExecutor,
- ControlsListingController controlsListingController) {
+ ControlsListingController controlsListingController,
+ ControlsController controlsController) {
mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme);
mWindowManagerFuncs = windowManagerFuncs;
mAudioManager = audioManager;
@@ -279,9 +287,46 @@
}
});
- mControlsListingController.addCallback(list -> mAnyControlsProviders = !list.isEmpty());
+ String preferredControlsPackage = mContext.getResources()
+ .getString(com.android.systemui.R.string.config_controlsPreferredPackage);
+ mControlsListingController.addCallback(list -> {
+ mAnyControlsProviders = !list.isEmpty();
+
+ /*
+ * See if any service providers match the preferred component. If they do,
+ * and there are no current favorites, and we haven't successfully loaded favorites to
+ * date, query the preferred component for a limited number of suggested controls.
+ */
+ ComponentName preferredComponent = null;
+ for (ControlsServiceInfo info : list) {
+ if (info.componentName.getPackageName().equals(preferredControlsPackage)) {
+ preferredComponent = info.componentName;
+ break;
+ }
+ }
+
+ if (preferredComponent == null) return;
+
+ SharedPreferences prefs = context.getSharedPreferences(PREFS_CONTROLS_FILE,
+ Context.MODE_PRIVATE);
+ boolean isSeeded = prefs.getBoolean(PREFS_CONTROLS_SEEDING_COMPLETED, false);
+ boolean hasFavorites = controlsController.getFavorites().size() > 0;
+ if (!isSeeded && !hasFavorites) {
+ controlsController.seedFavoritesForComponent(
+ preferredComponent,
+ (accepted) -> {
+ Log.i(TAG, "Controls seeded: " + accepted);
+ prefs.edit().putBoolean(PREFS_CONTROLS_SEEDING_COMPLETED,
+ accepted).apply();
+ }
+ );
+ }
+ });
}
+
+
+
/**
* Show the global actions dialog (creating if necessary)
*
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index a161d03..e208ee2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -33,7 +33,6 @@
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
-import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -64,6 +63,7 @@
public class MediaControlPanel implements NotificationMediaManager.MediaListener {
private static final String TAG = "MediaControlPanel";
private final NotificationMediaManager mMediaManager;
+ private final Executor mForegroundExecutor;
private final Executor mBackgroundExecutor;
private Context mContext;
@@ -102,15 +102,18 @@
* @param manager
* @param layoutId layout resource to use for this control panel
* @param actionIds resource IDs for action buttons in the layout
+ * @param foregroundExecutor foreground executor
* @param backgroundExecutor background executor, used for processing artwork
*/
public MediaControlPanel(Context context, ViewGroup parent, NotificationMediaManager manager,
- @LayoutRes int layoutId, int[] actionIds, Executor backgroundExecutor) {
+ @LayoutRes int layoutId, int[] actionIds, Executor foregroundExecutor,
+ Executor backgroundExecutor) {
mContext = context;
LayoutInflater inflater = LayoutInflater.from(mContext);
mMediaNotifView = (LinearLayout) inflater.inflate(layoutId, parent, false);
mMediaManager = manager;
mActionIds = actionIds;
+ mForegroundExecutor = foregroundExecutor;
mBackgroundExecutor = backgroundExecutor;
}
@@ -176,15 +179,17 @@
mMediaNotifView.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor));
// Click action
- mMediaNotifView.setOnClickListener(v -> {
- try {
- contentIntent.send();
- // Also close shade
- mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
- } catch (PendingIntent.CanceledException e) {
- Log.e(TAG, "Pending intent was canceled", e);
- }
- });
+ if (contentIntent != null) {
+ mMediaNotifView.setOnClickListener(v -> {
+ try {
+ contentIntent.send();
+ // Also close shade
+ mContext.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+ } catch (PendingIntent.CanceledException e) {
+ Log.e(TAG, "Pending intent was canceled", e);
+ }
+ });
+ }
// App icon
ImageView appIcon = mMediaNotifView.findViewById(R.id.icon);
@@ -316,7 +321,7 @@
// Now that it's resized, update the UI
final RoundedBitmapDrawable result = roundedDrawable;
- albumView.getHandler().post(() -> {
+ mForegroundExecutor.execute(() -> {
if (result != null) {
albumView.setImageDrawable(result);
albumView.setVisibility(View.VISIBLE);
@@ -335,8 +340,7 @@
if (mSeamless == null) {
return;
}
- Handler handler = mSeamless.getHandler();
- handler.post(() -> {
+ mForegroundExecutor.execute(() -> {
updateChipInternal(device);
});
}
@@ -401,12 +405,15 @@
new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
mContext.sendBroadcast(intent);
} else {
- Log.d(TAG, "No receiver to restart");
// If we don't have a receiver, try relaunching the activity instead
- try {
- mController.getSessionActivity().send();
- } catch (PendingIntent.CanceledException e) {
- Log.e(TAG, "Pending intent was canceled", e);
+ if (mController.getSessionActivity() != null) {
+ try {
+ mController.getSessionActivity().send();
+ } catch (PendingIntent.CanceledException e) {
+ Log.e(TAG, "Pending intent was canceled", e);
+ }
+ } else {
+ Log.e(TAG, "No receiver or activity to restart");
}
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index 88491b7..8be2502 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -229,8 +229,8 @@
*/
Rect getDestinationBounds(float aspectRatio, Rect bounds, Size minimalSize) {
final Rect destinationBounds;
- final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
if (bounds == null) {
+ final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
destinationBounds = new Rect(defaultBounds);
if (mReentrySnapFraction == INVALID_SNAP_FRACTION && mReentrySize == null) {
mOverrideMinimalSize = minimalSize;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
index 8fff419..25acce6 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
@@ -65,6 +65,7 @@
private final PointF mDownPoint = new PointF();
private final Point mMaxSize = new Point();
private final Point mMinSize = new Point();
+ private final Rect mLastResizeBounds = new Rect();
private final Rect mTmpBounds = new Rect();
private final int mDelta;
@@ -187,17 +188,13 @@
private void onMotionEvent(MotionEvent ev) {
int action = ev.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
+ mLastResizeBounds.setEmpty();
mAllowGesture = isWithinTouchRegion((int) ev.getX(), (int) ev.getY());
if (mAllowGesture) {
mDownPoint.set(ev.getX(), ev.getY());
}
} else if (mAllowGesture) {
- final Rect currentPipBounds = mMotionHelper.getBounds();
- Rect newSize = TaskResizingAlgorithm.resizeDrag(ev.getX(), ev.getY(), mDownPoint.x,
- mDownPoint.y, currentPipBounds, mCtrlType, mMinSize.x, mMinSize.y, mMaxSize,
- true, true);
- mPipBoundsHandler.transformBoundsToAspectRatio(newSize);
switch (action) {
case MotionEvent.ACTION_POINTER_DOWN:
// We do not support multi touch for resizing via drag
@@ -206,11 +203,16 @@
case MotionEvent.ACTION_MOVE:
// Capture inputs
mInputMonitor.pilferPointers();
- //TODO: Actually do resize here.
+ final Rect currentPipBounds = mMotionHelper.getBounds();
+ mLastResizeBounds.set(TaskResizingAlgorithm.resizeDrag(ev.getX(), ev.getY(),
+ mDownPoint.x, mDownPoint.y, currentPipBounds, mCtrlType, mMinSize.x,
+ mMinSize.y, mMaxSize, true, true));
+ mPipBoundsHandler.transformBoundsToAspectRatio(mLastResizeBounds);
+ mPipTaskOrganizer.scheduleResizePip(mLastResizeBounds, null);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
- //TODO: Finish resize operation here.
+ mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds);
mMotionHelper.synchronizePinnedStackBounds();
mCtrlType = CTRL_NONE;
mAllowGesture = false;
@@ -223,7 +225,7 @@
mMaxSize.set(maxX, maxY);
}
- void updateMiniSize(int minX, int minY) {
+ void updateMinSize(int minX, int minY) {
mMinSize.set(minX, minY);
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index b5fb1a9..9b67d80 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -42,6 +42,7 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.systemui.R;
import com.android.systemui.pip.PipBoundsHandler;
@@ -74,7 +75,7 @@
private final Context mContext;
private final IActivityManager mActivityManager;
private final PipBoundsHandler mPipBoundsHandler;
- private final PipResizeGestureHandler mPipResizeGestureHandler;
+ private PipResizeGestureHandler mPipResizeGestureHandler;
private IPinnedStackController mPinnedStackController;
private final PipMenuActivityController mMenuController;
@@ -85,14 +86,17 @@
// The current movement bounds
private Rect mMovementBounds = new Rect();
+ // The current resized bounds, changed by user resize.
+ // This is used during expand/un-expand to save/restore the user's resized size.
+ @VisibleForTesting Rect mResizedBounds = new Rect();
// The reference inset bounds, used to determine the dismiss fraction
private Rect mInsetBounds = new Rect();
// The reference bounds used to calculate the normal/expanded target bounds
private Rect mNormalBounds = new Rect();
- private Rect mNormalMovementBounds = new Rect();
+ @VisibleForTesting Rect mNormalMovementBounds = new Rect();
private Rect mExpandedBounds = new Rect();
- private Rect mExpandedMovementBounds = new Rect();
+ @VisibleForTesting Rect mExpandedMovementBounds = new Rect();
private int mExpandedShortestEdgeSize;
// Used to workaround an issue where the WM rotation happens before we are notified, allowing
@@ -127,7 +131,7 @@
private final PipTouchState mTouchState;
private final FlingAnimationUtils mFlingAnimationUtils;
private final FloatingContentCoordinator mFloatingContentCoordinator;
- private final PipMotionHelper mMotionHelper;
+ private PipMotionHelper mMotionHelper;
private PipTouchGesture mGesture;
// Temp vars
@@ -240,14 +244,15 @@
mFloatingContentCoordinator.onContentRemoved(mMotionHelper);
}
+ mResizedBounds.setEmpty();
mPipResizeGestureHandler.onActivityUnpinned();
}
public void onPinnedStackAnimationEnded() {
// Always synchronize the motion helper bounds once PiP animations finish
mMotionHelper.synchronizePinnedStackBounds();
- mPipResizeGestureHandler.updateMiniSize(mMotionHelper.getBounds().width(),
- mMotionHelper.getBounds().height());
+ updateMovementBounds();
+ mResizedBounds.set(mMotionHelper.getBounds());
if (mShowPipMenuOnAnimationEnd) {
mMenuController.showMenu(MENU_STATE_CLOSE, mMotionHelper.getBounds(),
@@ -292,11 +297,13 @@
Size expandedSize = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio,
mExpandedShortestEdgeSize, displaySize.x, displaySize.y);
mExpandedBounds.set(0, 0, expandedSize.getWidth(), expandedSize.getHeight());
- mPipResizeGestureHandler.updateMaxSize(expandedSize.getWidth(), expandedSize.getHeight());
Rect expandedMovementBounds = new Rect();
mSnapAlgorithm.getMovementBounds(mExpandedBounds, insetBounds, expandedMovementBounds,
bottomOffset);
+ mPipResizeGestureHandler.updateMinSize(mNormalBounds.width(), mNormalBounds.height());
+ mPipResizeGestureHandler.updateMaxSize(mExpandedBounds.width(), mExpandedBounds.height());
+
// The extra offset does not really affect the movement bounds, but are applied based on the
// current state (ime showing, or shelf offset) when we need to actually shift
int extraOffset = Math.max(
@@ -332,7 +339,7 @@
mExpandedMovementBounds = expandedMovementBounds;
mDisplayRotation = displayRotation;
mInsetBounds.set(insetBounds);
- updateMovementBounds(mMenuState);
+ updateMovementBounds();
mMovementBoundsExtraOffsets = extraOffset;
// If we have a deferred resize, apply it now
@@ -392,7 +399,7 @@
case MotionEvent.ACTION_UP: {
// Update the movement bounds again if the state has changed since the user started
// dragging (ie. when the IME shows)
- updateMovementBounds(mMenuState);
+ updateMovementBounds();
if (mGesture.onUp(mTouchState)) {
break;
@@ -490,9 +497,11 @@
if (menuState == MENU_STATE_FULL && mMenuState != MENU_STATE_FULL) {
// Save the current snap fraction and if we do not drag or move the PiP, then
// we store back to this snap fraction. Otherwise, we'll reset the snap
- // fraction and snap to the closest edge
- Rect expandedBounds = new Rect(mExpandedBounds);
+ // fraction and snap to the closest edge.
+ // Also save the current resized bounds so when the menu disappears, we can restore it.
if (resize) {
+ mResizedBounds.set(mMotionHelper.getBounds());
+ Rect expandedBounds = new Rect(mExpandedBounds);
mSavedSnapFraction = mMotionHelper.animateToExpandedState(expandedBounds,
mMovementBounds, mExpandedMovementBounds);
}
@@ -520,9 +529,12 @@
}
if (mDeferResizeToNormalBoundsUntilRotation == -1) {
- Rect normalBounds = new Rect(mNormalBounds);
- mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
- mNormalMovementBounds, mMovementBounds, false /* immediate */);
+ Rect restoreBounds = new Rect(mResizedBounds);
+ Rect restoredMovementBounds = new Rect();
+ mSnapAlgorithm.getMovementBounds(restoreBounds, mInsetBounds,
+ restoredMovementBounds, mIsImeShowing ? mImeHeight : 0);
+ mMotionHelper.animateToUnexpandedState(restoreBounds, mSavedSnapFraction,
+ restoredMovementBounds, mMovementBounds, false /* immediate */);
mSavedSnapFraction = -1f;
}
} else {
@@ -533,7 +545,7 @@
}
}
mMenuState = menuState;
- updateMovementBounds(menuState);
+ updateMovementBounds();
// If pip menu has dismissed, we should register the A11y ActionReplacingConnection for pip
// as well, or it can't handle a11y focus and pip menu can't perform any action.
onRegistrationChanged(menuState == MENU_STATE_NONE);
@@ -549,6 +561,21 @@
return mMotionHelper;
}
+ @VisibleForTesting
+ PipResizeGestureHandler getPipResizeGestureHandler() {
+ return mPipResizeGestureHandler;
+ }
+
+ @VisibleForTesting
+ void setPipResizeGestureHandler(PipResizeGestureHandler pipResizeGestureHandler) {
+ mPipResizeGestureHandler = pipResizeGestureHandler;
+ }
+
+ @VisibleForTesting
+ void setPipMotionHelper(PipMotionHelper pipMotionHelper) {
+ mMotionHelper = pipMotionHelper;
+ }
+
/**
* @return the unexpanded bounds.
*/
@@ -709,14 +736,14 @@
* Updates the current movement bounds based on whether the menu is currently visible and
* resized.
*/
- private void updateMovementBounds(int menuState) {
- boolean isMenuExpanded = menuState == MENU_STATE_FULL;
- mMovementBounds = isMenuExpanded && willResizeMenu()
- ? mExpandedMovementBounds
- : mNormalMovementBounds;
- mPipBoundsHandler.setMinEdgeSize(
- isMenuExpanded ? mExpandedShortestEdgeSize : 0);
+ private void updateMovementBounds() {
+ mSnapAlgorithm.getMovementBounds(mMotionHelper.getBounds(), mInsetBounds,
+ mMovementBounds, mIsImeShowing ? mImeHeight : 0);
mMotionHelper.setCurrentMovementBounds(mMovementBounds);
+
+ boolean isMenuExpanded = mMenuState == MENU_STATE_FULL;
+ mPipBoundsHandler.setMinEdgeSize(
+ isMenuExpanded && willResizeMenu() ? mExpandedShortestEdgeSize : 0);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
index 3cf0718..ece1ce8b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
@@ -28,6 +28,7 @@
void forceCollapsePanels();
void openPanels();
Context getContext();
+ Context getUserContext();
QSLogger getQSLogger();
Collection<QSTile> getTiles();
void addCallback(Callback callback);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
index 837256b..d5e5b10 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
@@ -55,11 +55,13 @@
* @param context
* @param parent
* @param manager
+ * @param foregroundExecutor
* @param backgroundExecutor
*/
public QSMediaPlayer(Context context, ViewGroup parent, NotificationMediaManager manager,
- Executor backgroundExecutor) {
- super(context, parent, manager, R.layout.qs_media_panel, QS_ACTION_IDS, backgroundExecutor);
+ Executor foregroundExecutor, Executor backgroundExecutor) {
+ super(context, parent, manager, R.layout.qs_media_panel, QS_ACTION_IDS, foregroundExecutor,
+ backgroundExecutor);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index bf72b33..5ccf8c7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -53,6 +53,7 @@
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
@@ -101,6 +102,7 @@
private final ArrayList<QSMediaPlayer> mMediaPlayers = new ArrayList<>();
private final NotificationMediaManager mNotificationMediaManager;
private final LocalBluetoothManager mLocalBluetoothManager;
+ private final Executor mForegroundExecutor;
private final Executor mBackgroundExecutor;
private LocalMediaManager mLocalMediaManager;
private MediaDevice mDevice;
@@ -160,6 +162,7 @@
BroadcastDispatcher broadcastDispatcher,
QSLogger qsLogger,
NotificationMediaManager notificationMediaManager,
+ @Main Executor foregroundExecutor,
@Background Executor backgroundExecutor,
@Nullable LocalBluetoothManager localBluetoothManager
) {
@@ -168,6 +171,7 @@
mQSLogger = qsLogger;
mDumpManager = dumpManager;
mNotificationMediaManager = notificationMediaManager;
+ mForegroundExecutor = foregroundExecutor;
mBackgroundExecutor = backgroundExecutor;
mLocalBluetoothManager = localBluetoothManager;
@@ -270,7 +274,7 @@
if (player == null) {
Log.d(TAG, "creating new player");
player = new QSMediaPlayer(mContext, this, mNotificationMediaManager,
- mBackgroundExecutor);
+ mForegroundExecutor, mBackgroundExecutor);
if (player.isPlaying()) {
mMediaCarousel.addView(player.getView(), 0, lp); // add in front
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index fab7191..9e8eb3a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -45,7 +45,6 @@
import com.android.systemui.qs.external.TileLifecycleManager;
import com.android.systemui.qs.external.TileServices;
import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.phone.AutoTileManager;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -98,7 +97,7 @@
@Inject
public QSTileHost(Context context,
StatusBarIconController iconController,
- QSFactoryImpl defaultFactory,
+ QSFactory defaultFactory,
@Main Handler mainHandler,
@Background Looper bgLooper,
PluginManager pluginManager,
@@ -120,7 +119,6 @@
mServices = new TileServices(this, bgLooper, mBroadcastDispatcher);
mStatusBarOptional = statusBarOptional;
- defaultFactory.setHost(this);
mQsFactories.add(defaultFactory);
pluginManager.addPluginListener(this, QSFactory.class, true);
mDumpManager.registerDumpable(TAG, this);
@@ -211,10 +209,12 @@
return mContext;
}
+ @Override
public Context getUserContext() {
return mUserContext;
}
+ @Override
public TileServices getTileServices() {
return mServices;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java
index 4512afb..0c50194 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSMediaPlayer.java
@@ -48,12 +48,13 @@
* @param context
* @param parent
* @param manager
+ * @param foregroundExecutor
* @param backgroundExecutor
*/
public QuickQSMediaPlayer(Context context, ViewGroup parent, NotificationMediaManager manager,
- Executor backgroundExecutor) {
+ Executor foregroundExecutor, Executor backgroundExecutor) {
super(context, parent, manager, R.layout.qqs_media_panel, QQS_ACTION_IDS,
- backgroundExecutor);
+ foregroundExecutor, backgroundExecutor);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 6654b7a..be01d75 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -32,6 +32,7 @@
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.SignalState;
@@ -79,11 +80,12 @@
BroadcastDispatcher broadcastDispatcher,
QSLogger qsLogger,
NotificationMediaManager notificationMediaManager,
+ @Main Executor foregroundExecutor,
@Background Executor backgroundExecutor,
@Nullable LocalBluetoothManager localBluetoothManager
) {
super(context, attrs, dumpManager, broadcastDispatcher, qsLogger, notificationMediaManager,
- backgroundExecutor, localBluetoothManager);
+ foregroundExecutor, backgroundExecutor, localBluetoothManager);
if (mFooter != null) {
removeView(mFooter.getView());
}
@@ -103,7 +105,7 @@
int marginSize = (int) mContext.getResources().getDimension(R.dimen.qqs_media_spacing);
mMediaPlayer = new QuickQSMediaPlayer(mContext, mHorizontalLinearLayout,
- notificationMediaManager, backgroundExecutor);
+ notificationMediaManager, foregroundExecutor, backgroundExecutor);
LayoutParams lp2 = new LayoutParams(0, LayoutParams.MATCH_PARENT, 1);
lp2.setMarginEnd(marginSize);
lp2.setMarginStart(0);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index d422dd7..11b625f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -436,6 +436,10 @@
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ // Handle padding of QuickStatusBarHeader
+ setPadding(mRoundedCornerPadding, getPaddingTop(), mRoundedCornerPadding,
+ getPaddingBottom());
+
// Handle padding of SystemIconsView
DisplayCutout cutout = insets.getDisplayCutout();
Pair<Integer, Integer> cornerCutoutPadding = StatusBarWindowView.cornerCutoutMargins(
@@ -450,8 +454,11 @@
int statusBarPaddingRight = isLayoutRtl()
? getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start)
: getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end);
- mSystemIconsView.setPadding(padding.first + statusBarPaddingLeft, waterfallTopInset,
- padding.second + statusBarPaddingRight, 0);
+ mSystemIconsView.setPadding(
+ Math.max(padding.first + statusBarPaddingLeft - mRoundedCornerPadding, 0),
+ waterfallTopInset,
+ Math.max(padding.second + statusBarPaddingRight - mRoundedCornerPadding, 0),
+ 0);
return super.onApplyWindowInsets(insets);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 3b27fb7..08c8f86 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -46,7 +46,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
import com.android.systemui.qs.tileimpl.QSTileImpl;
@@ -79,7 +79,7 @@
private boolean mIsTokenGranted;
private boolean mIsShowingDialog;
- private CustomTile(QSTileHost host, String action, Context userContext) {
+ private CustomTile(QSHost host, String action, Context userContext) {
super(host);
mWindowManager = WindowManagerGlobal.getWindowManagerService();
mComponent = ComponentName.unflattenFromString(action);
@@ -392,7 +392,7 @@
return ComponentName.unflattenFromString(action);
}
- public static CustomTile create(QSTileHost host, String spec, Context userContext) {
+ public static CustomTile create(QSHost host, String spec, Context userContext) {
if (spec == null || !spec.startsWith(PREFIX) || !spec.endsWith(")")) {
throw new IllegalArgumentException("Bad custom tile spec: " + spec);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 1b8717b..c182a58 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -24,7 +24,7 @@
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
-import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.tiles.AirplaneModeTile;
import com.android.systemui.qs.tiles.BatterySaverTile;
@@ -51,6 +51,8 @@
import javax.inject.Provider;
import javax.inject.Singleton;
+import dagger.Lazy;
+
@Singleton
public class QSFactoryImpl implements QSFactory {
@@ -77,10 +79,11 @@
private final Provider<UiModeNightTile> mUiModeNightTileProvider;
private final Provider<ScreenRecordTile> mScreenRecordTileProvider;
- private QSTileHost mHost;
+ private final Lazy<QSHost> mQsHostLazy;
@Inject
- public QSFactoryImpl(Provider<WifiTile> wifiTileProvider,
+ public QSFactoryImpl(Lazy<QSHost> qsHostLazy,
+ Provider<WifiTile> wifiTileProvider,
Provider<BluetoothTile> bluetoothTileProvider,
Provider<CellularTile> cellularTileProvider,
Provider<DndTile> dndTileProvider,
@@ -100,6 +103,7 @@
Provider<GarbageMonitor.MemoryTile> memoryTileProvider,
Provider<UiModeNightTile> uiModeNightTileProvider,
Provider<ScreenRecordTile> screenRecordTileProvider) {
+ mQsHostLazy = qsHostLazy;
mWifiTileProvider = wifiTileProvider;
mBluetoothTileProvider = bluetoothTileProvider;
mCellularTileProvider = cellularTileProvider;
@@ -122,10 +126,6 @@
mScreenRecordTileProvider = screenRecordTileProvider;
}
- public void setHost(QSTileHost host) {
- mHost = host;
- }
-
public QSTile createTile(String tileSpec) {
QSTileImpl tile = createTileInternal(tileSpec);
if (tile != null) {
@@ -179,7 +179,8 @@
// Custom tiles
if (tileSpec.startsWith(CustomTile.PREFIX)) {
- return CustomTile.create(mHost, tileSpec, mHost.getUserContext());
+ return CustomTile.create(mQsHostLazy.get(), tileSpec,
+ mQsHostLazy.get().getUserContext());
}
// Debug tiles.
@@ -196,7 +197,7 @@
@Override
public QSTileView createTileView(QSTile tile, boolean collapsedView) {
- Context context = new ContextThemeWrapper(mHost.getContext(), R.style.qs_theme);
+ Context context = new ContextThemeWrapper(mQsHostLazy.get().getContext(), R.style.qs_theme);
QSIconView icon = tile.createTileView(context);
if (collapsedView) {
return new QSTileBaseView(context, icon, collapsedView);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 7c770f4..1780fb1 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -347,6 +347,7 @@
void handleImageAsScreenshot(Bitmap screenshot, Rect screenshotScreenBounds,
Insets visibleInsets, int taskId, Consumer<Uri> finisher) {
// TODO use taskId and visibleInsets
+ clearScreenshot("new screenshot requested");
takeScreenshot(screenshot, finisher, screenshotScreenBounds);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index fabe3a7..b357ada 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -45,7 +45,6 @@
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
private final Handler mHandler;
- private NotificationPresenter mPresenter;
private boolean mPanelExpanded;
private boolean mScreenOn;
private boolean mReorderingAllowed;
@@ -80,7 +79,6 @@
}
public void setUpWithPresenter(NotificationPresenter presenter) {
- mPresenter = presenter;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
index b960b42..2c747bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.collection;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
@@ -51,6 +52,7 @@
return mSummary;
}
+ @NonNull
public List<NotificationEntry> getChildren() {
return mUnmodifiableChildren;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewBarn.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewBarn.kt
new file mode 100644
index 0000000..e7948cd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewBarn.kt
@@ -0,0 +1,63 @@
+/*
+ * 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 android.view.textclassifier.Log
+import com.android.systemui.statusbar.notification.stack.NotificationListItem
+import java.lang.IllegalStateException
+
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * The ViewBarn is just a map from [ListEntry] to an instance of [NotificationListItem] which is
+ * usually just an [ExpandableNotificationRow]
+ */
+@Singleton
+class NotifViewBarn @Inject constructor() {
+ private val DEBUG = false
+
+ private val rowMap = mutableMapOf<String, NotificationListItem>()
+
+ fun requireView(forEntry: ListEntry): NotificationListItem {
+ if (DEBUG) {
+ Log.d(TAG, "requireView: $forEntry.key")
+ }
+ val li = rowMap[forEntry.key]
+ if (li == null) {
+ throw IllegalStateException("No view has been registered for entry: $forEntry")
+ }
+
+ return li
+ }
+
+ fun registerViewForEntry(entry: ListEntry, view: NotificationListItem) {
+ if (DEBUG) {
+ Log.d(TAG, "registerViewForEntry: $entry.key")
+ }
+ rowMap[entry.key] = view
+ }
+
+ fun removeViewForEntry(entry: ListEntry) {
+ if (DEBUG) {
+ Log.d(TAG, "removeViewForEntry: $entry.key")
+ }
+ rowMap.remove(entry.key)
+ }
+}
+
+private const val TAG = "NotifViewBarn"
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewManager.kt
new file mode 100644
index 0000000..0437877d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewManager.kt
@@ -0,0 +1,200 @@
+/*
+ * 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
+
+import android.annotation.MainThread
+import android.view.ViewGroup
+
+import com.android.systemui.statusbar.FeatureFlags
+import com.android.systemui.statusbar.notification.VisualStabilityManager
+import com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY
+import com.android.systemui.statusbar.notification.stack.NotificationListItem
+import com.android.systemui.util.Assert
+
+import java.io.FileDescriptor
+import java.io.PrintWriter
+import java.lang.IllegalStateException
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * A consumer of a Notification tree built by [ShadeListBuilder] which will update the notification
+ * presenter with the minimum operations required to make the old tree match the new one
+ */
+@MainThread
+@Singleton
+class NotifViewManager @Inject constructor(
+ private val rowRegistry: NotifViewBarn,
+ private val stabilityManager: VisualStabilityManager,
+ private val featureFlags: FeatureFlags
+) {
+ var currentNotifs = listOf<ListEntry>()
+
+ private lateinit var listContainer: SimpleNotificationListContainer
+
+ fun attach(listBuilder: ShadeListBuilder) {
+ if (featureFlags.isNewNotifPipelineRenderingEnabled) {
+ listBuilder.setOnRenderListListener { entries: List<ListEntry> ->
+ this.onNotifTreeBuilt(entries)
+ }
+ }
+ }
+
+ fun setViewConsumer(consumer: SimpleNotificationListContainer) {
+ listContainer = consumer
+ }
+
+ /**
+ * Callback for when the tree is rebuilt
+ */
+ fun onNotifTreeBuilt(notifList: List<ListEntry>) {
+ Assert.isMainThread()
+
+ /*
+ * The assumption here is that anything from the old NotificationViewHierarchyManager that
+ * is responsible for filtering is done via the NotifFilter logic. This tree we get should
+ * be *the stuff to display* +/- redacted stuff
+ */
+
+ detachRows(notifList)
+ attachRows(notifList)
+
+ currentNotifs = notifList
+ }
+
+ private fun detachRows(entries: List<ListEntry>) {
+ // To properly detach rows, we are looking to remove any view in the consumer that is not
+ // present in the incoming list.
+ //
+ // Every listItem was top-level, so it's entry's parent was ROOT_ENTRY, but now
+ // there are two possibilities:
+ //
+ // 1. It is not present in the entry list
+ // 1a. It has moved to be a child in the entry list - transfer it
+ // 1b. It is gone completely - remove it
+ // 2. It is present in the entry list - diff the children
+ getListItems(listContainer)
+ .filter {
+ // Ignore things that are showing the blocking helper
+ !it.isBlockingHelperShowing
+ }
+ .forEach { listItem ->
+ val noLongerTopLevel = listItem.entry.parent != ROOT_ENTRY
+ val becameChild = noLongerTopLevel && listItem.entry.parent != null
+
+ val idx = entries.indexOf(listItem.entry)
+
+ if (noLongerTopLevel) {
+ // Summaries won't become children; remove the whole group
+ if (listItem.isSummaryWithChildren) {
+ listItem.removeAllChildren()
+ }
+
+ if (becameChild) {
+ // Top-level element is becoming a child, don't generate an animation
+ listContainer.setChildTransferInProgress(true)
+ }
+ listContainer.removeListItem(listItem)
+ listContainer.setChildTransferInProgress(false)
+ } else if (entries[idx] is GroupEntry) {
+ // A top-level entry exists. If it's a group, diff the children
+ val groupChildren = (entries[idx] as GroupEntry).children
+ listItem.notificationChildren?.forEach { listChild ->
+ if (!groupChildren.contains(listChild.entry)) {
+ listItem.removeChildNotification(listChild)
+
+ // TODO: the old code only calls this if the notif is gone from
+ // NEM.getActiveNotificationUnfiltered(). Do we care?
+ listContainer.notifyGroupChildRemoved(
+ listChild.view, listChild.view.parent as ViewGroup)
+ }
+ }
+ }
+ }
+ }
+
+ /** Convenience method for getting a sequence of [NotificationListItem]s */
+ private fun getListItems(container: SimpleNotificationListContainer):
+ Sequence<NotificationListItem> {
+ return (0 until container.getContainerChildCount()).asSequence()
+ .map { container.getContainerChildAt(it) }
+ .filterIsInstance<NotificationListItem>()
+ }
+
+ private fun attachRows(entries: List<ListEntry>) {
+
+ var orderChanged = false
+
+ // To attach rows we can use _this one weird trick_: if the intended view to add does not
+ // have a parent, then simply add it (and its children).
+ entries.forEach { entry ->
+ val listItem = rowRegistry.requireView(entry)
+
+ if (listItem.view.parent != null) {
+ listContainer.addListItem(listItem)
+ stabilityManager.notifyViewAddition(listItem.view)
+ }
+
+ if (entry is GroupEntry) {
+ for ((idx, childEntry) in entry.children.withIndex()) {
+ val childListItem = rowRegistry.requireView(childEntry)
+ // Child hasn't been added yet. add it!
+ if (!listItem.notificationChildren.contains(childListItem)) {
+ // TODO: old code here just Log.wtf()'d here. This might wreak havoc
+ if (childListItem.view.parent != null) {
+ throw IllegalStateException("trying to add a notification child that " +
+ "already has a parent. class: " +
+ "${childListItem.view.parent?.javaClass} " +
+ "\n child: ${childListItem.view}"
+ )
+ }
+
+ listItem.addChildNotification(childListItem, idx)
+ stabilityManager.notifyViewAddition(childListItem.view)
+ listContainer.notifyGroupChildAdded(childListItem.view)
+ }
+ }
+
+ // finally after removing and adding has been performed we can apply the order
+ orderChanged = orderChanged ||
+ listItem.applyChildOrder(
+ getChildListFromParent(entry),
+ stabilityManager,
+ null /*TODO: stability callback */
+ )
+ }
+ }
+
+ if (orderChanged) {
+ listContainer.generateChildOrderChangedEvent()
+ }
+ }
+
+ private fun getChildListFromParent(parent: ListEntry): List<NotificationListItem> {
+ if (parent is GroupEntry) {
+ return parent.children.map { child -> rowRegistry.requireView(child) }
+ .toList()
+ }
+
+ return emptyList()
+ }
+
+ fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
+ }
+}
+
+private const val TAG = "NotifViewDataSource"
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 5b73b1a..f7d6cef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -319,7 +319,7 @@
logParentingChanges();
freeEmptyGroups();
- // Step 6: Dispatch the new list, first to any listeners and then to the view layer
+ // Step 8: Dispatch the new list, first to any listeners and then to the view layer
if (mIterationCount % 10 == 0) {
mLogger.logFinalList(mNotifList);
}
@@ -328,7 +328,7 @@
mOnRenderListListener.onRenderList(mReadOnlyNotifList);
}
- // Step 7: We're done!
+ // Step 9: We're done!
mLogger.logEndBuildList(mIterationCount);
mPipelineState.setState(STATE_IDLE);
mIterationCount++;
@@ -816,7 +816,7 @@
* @param entries A read-only view into the current notif list. Note that this list is
* backed by the live list and will change in response to new pipeline runs.
*/
- void onRenderList(List<ListEntry> entries);
+ void onRenderList(@NonNull List<ListEntry> entries);
}
private static final NotifSection sDefaultSection =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SimpleNotificationListContainer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SimpleNotificationListContainer.kt
new file mode 100644
index 0000000..2dbe555
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SimpleNotificationListContainer.kt
@@ -0,0 +1,43 @@
+/*
+ * 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 android.view.View
+import android.view.ViewGroup
+import com.android.systemui.statusbar.notification.stack.NotificationListItem
+
+/**
+ * Minimal interface of what [NotifViewManager] needs from [NotificationListContainer]
+ */
+interface SimpleNotificationListContainer {
+ /** Called to signify that a top-level element is becoming a child in the shade */
+ fun setChildTransferInProgress(b: Boolean)
+ /** Used to generate a list of [NotificationListItem] */
+ fun getContainerChildAt(i: Int): View
+ /** Similar to above */
+ fun getContainerChildCount(): Int
+ /** Remove a [NotificationListItem] from the container */
+ fun removeListItem(li: NotificationListItem)
+ /** Add a [NotificationListItem] to the container */
+ fun addListItem(li: NotificationListItem)
+ /** Allows [NotifViewManager] to notify the container about a group child removal */
+ fun notifyGroupChildRemoved(row: View, parent: ViewGroup)
+ /** Allows [NotifViewManager] to notify the container about a group child addition */
+ fun notifyGroupChildAdded(row: View)
+ /** [NotifViewManager] calls this when the order of the children changes */
+ fun generateChildOrderChangedEvent()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
new file mode 100644
index 0000000..573c129
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
@@ -0,0 +1,171 @@
+/*
+ * 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.coordinator;
+
+import static com.android.systemui.statusbar.NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY;
+
+import android.annotation.Nullable;
+
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
+
+import java.util.Objects;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Coordinates heads up notification (HUN) interactions with the notification pipeline based on
+ * the HUN state reported by the {@link HeadsUpManager}. In this class we only consider one
+ * notification, in particular the {@link HeadsUpManager#getTopEntry()}, to be HeadsUpping at a
+ * time even though other notifications may be queued to heads up next.
+ *
+ * The current HUN, but not HUNs that are queued to heads up, will be:
+ * - Lifetime extended until it's no longer heads upping.
+ * - Promoted out of its group if it's a child of a group.
+ * - In the HeadsUpCoordinatorSection. Ordering is configured in {@link NotifCoordinators}.
+ * - Removed from HeadsUpManager if it's removed from the NotificationCollection.
+ *
+ * Note: The inflation callback in {@link PreparationCoordinator} handles showing HUNs.
+ */
+@Singleton
+public class HeadsUpCoordinator implements Coordinator {
+ private static final String TAG = "HeadsUpCoordinator";
+
+ private final HeadsUpManager mHeadsUpManager;
+ private final NotificationRemoteInputManager mRemoteInputManager;
+
+ // tracks the current HeadUpNotification reported by HeadsUpManager
+ private @Nullable NotificationEntry mCurrentHun;
+
+ private NotifLifetimeExtender.OnEndLifetimeExtensionCallback mEndLifetimeExtension;
+ private NotificationEntry mNotifExtendingLifetime; // notif we've extended the lifetime for
+
+ @Inject
+ public HeadsUpCoordinator(
+ HeadsUpManager headsUpManager,
+ NotificationRemoteInputManager remoteInputManager) {
+ mHeadsUpManager = headsUpManager;
+ mRemoteInputManager = remoteInputManager;
+ }
+
+ @Override
+ public void attach(NotifPipeline pipeline) {
+ mHeadsUpManager.addListener(mOnHeadsUpChangedListener);
+ pipeline.addCollectionListener(mNotifCollectionListener);
+ pipeline.addPromoter(mNotifPromoter);
+ pipeline.addNotificationLifetimeExtender(mLifetimeExtender);
+ }
+
+ @Override
+ public NotifSection getSection() {
+ return mNotifSection;
+ }
+
+ private final NotifCollectionListener mNotifCollectionListener = new NotifCollectionListener() {
+ /**
+ * Stop alerting HUNs that are removed from the notification collection
+ */
+ @Override
+ public void onEntryRemoved(NotificationEntry entry, int reason) {
+ final String entryKey = entry.getKey();
+ if (mHeadsUpManager.isAlerting(entryKey)) {
+ boolean removeImmediatelyForRemoteInput =
+ mRemoteInputManager.getController().isSpinning(entryKey)
+ && !FORCE_REMOTE_INPUT_HISTORY;
+ mHeadsUpManager.removeNotification(entry.getKey(), removeImmediatelyForRemoteInput);
+ }
+ }
+ };
+
+ private final NotifLifetimeExtender mLifetimeExtender = new NotifLifetimeExtender() {
+ @Override
+ public String getName() {
+ return TAG;
+ }
+
+ @Override
+ public void setCallback(OnEndLifetimeExtensionCallback callback) {
+ mEndLifetimeExtension = callback;
+ }
+
+ @Override
+ public boolean shouldExtendLifetime(NotificationEntry entry, int reason) {
+ boolean isShowingHun = isCurrentlyShowingHun(entry);
+ if (isShowingHun) {
+ mNotifExtendingLifetime = entry;
+ }
+ return isShowingHun;
+ }
+
+ @Override
+ public void cancelLifetimeExtension(NotificationEntry entry) {
+ if (Objects.equals(mNotifExtendingLifetime, entry)) {
+ mNotifExtendingLifetime = null;
+ }
+ }
+ };
+
+ private final NotifPromoter mNotifPromoter = new NotifPromoter(TAG) {
+ @Override
+ public boolean shouldPromoteToTopLevel(NotificationEntry entry) {
+ return isCurrentlyShowingHun(entry);
+ }
+ };
+
+ private final NotifSection mNotifSection = new NotifSection(TAG) {
+ @Override
+ public boolean isInSection(ListEntry entry) {
+ return isCurrentlyShowingHun(entry);
+ }
+ };
+
+ private final OnHeadsUpChangedListener mOnHeadsUpChangedListener =
+ new OnHeadsUpChangedListener() {
+ @Override
+ public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
+ NotificationEntry newHUN = mHeadsUpManager.getTopEntry();
+ if (!Objects.equals(mCurrentHun, newHUN)) {
+ endNotifLifetimeExtension();
+ mCurrentHun = newHUN;
+ mNotifPromoter.invalidateList();
+ mNotifSection.invalidateList();
+ }
+ }
+ };
+
+ private boolean isCurrentlyShowingHun(ListEntry entry) {
+ return mCurrentHun == entry.getRepresentativeEntry();
+ }
+
+ private void endNotifLifetimeExtension() {
+ if (mNotifExtendingLifetime != null) {
+ mEndLifetimeExtension.onEndLifetimeExtension(
+ mLifetimeExtender,
+ mNotifExtendingLifetime);
+ mNotifExtendingLifetime = null;
+ }
+ }
+}
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 7a22d75..98104f8 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
@@ -49,6 +49,7 @@
public NotifCoordinators(
DumpManager dumpManager,
FeatureFlags featureFlags,
+ HeadsUpCoordinator headsUpCoordinator,
KeyguardCoordinator keyguardCoordinator,
RankingCoordinator rankingCoordinator,
ForegroundCoordinator foregroundCoordinator,
@@ -56,7 +57,6 @@
BubbleCoordinator bubbleCoordinator,
PreparationCoordinator preparationCoordinator) {
dumpManager.registerDumpable(TAG, this);
-
mCoordinators.add(new HideLocallyDismissedNotifsCoordinator());
mCoordinators.add(keyguardCoordinator);
mCoordinators.add(rankingCoordinator);
@@ -64,9 +64,10 @@
mCoordinators.add(deviceProvisionedCoordinator);
mCoordinators.add(bubbleCoordinator);
if (featureFlags.isNewNotifPipelineRenderingEnabled()) {
+ mCoordinators.add(headsUpCoordinator);
mCoordinators.add(preparationCoordinator);
}
- // TODO: add new Coordinators here! (b/145134683, b/112656837)
+ // TODO: add new Coordinators here! (b/112656837)
// TODO: add the sections in a particular ORDER (HeadsUp < People < Alerting)
for (Coordinator c : mCoordinators) {
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 ebecf18..742615c 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
@@ -26,13 +26,16 @@
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.NotifViewBarn;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
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.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -57,21 +60,31 @@
private final PreparationCoordinatorLogger mLogger;
private final NotifInflater mNotifInflater;
private final NotifInflationErrorManager mNotifErrorManager;
+ private final NotifViewBarn mViewBarn;
private final Map<NotificationEntry, Integer> mInflationStates = new ArrayMap<>();
private final IStatusBarService mStatusBarService;
+ private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
+ private final HeadsUpManager mHeadsUpManager;
@Inject
public PreparationCoordinator(
PreparationCoordinatorLogger logger,
NotifInflaterImpl notifInflater,
NotifInflationErrorManager errorManager,
- IStatusBarService service) {
+ NotifViewBarn viewBarn,
+ IStatusBarService service,
+ NotificationInterruptStateProvider notificationInterruptStateProvider,
+ HeadsUpManager headsUpManager
+ ) {
mLogger = logger;
mNotifInflater = notifInflater;
mNotifInflater.setInflationCallback(mInflationCallback);
mNotifErrorManager = errorManager;
mNotifErrorManager.addInflationErrorListener(mInflationErrorListener);
+ mViewBarn = viewBarn;
mStatusBarService = service;
+ mNotificationInterruptStateProvider = notificationInterruptStateProvider;
+ mHeadsUpManager = headsUpManager;
}
@Override
@@ -109,6 +122,7 @@
@Override
public void onEntryCleanUp(NotificationEntry entry) {
mInflationStates.remove(entry);
+ mViewBarn.removeViewForEntry(entry);
}
};
@@ -142,7 +156,13 @@
@Override
public void onInflationFinished(NotificationEntry entry) {
mLogger.logNotifInflated(entry.getKey());
+ mViewBarn.registerViewForEntry(entry, entry.getRow());
mInflationStates.put(entry, STATE_INFLATED);
+
+ // TODO: should eventually be moved to HeadsUpCoordinator
+ if (mNotificationInterruptStateProvider.shouldHeadsUp(entry)) {
+ mHeadsUpManager.showNotification(entry);
+ }
mNotifInflatingFilter.invalidateList();
}
};
@@ -151,6 +171,7 @@
new NotifInflationErrorManager.NotifInflationErrorListener() {
@Override
public void onNotifInflationError(NotificationEntry entry, Exception e) {
+ mViewBarn.removeViewForEntry(entry);
mInflationStates.put(entry, STATE_ERROR);
try {
final StatusBarNotification sbn = entry.getSbn();
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
deleted file mode 100644
index 15f312d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/FakePipelineConsumer.java
+++ /dev/null
@@ -1,85 +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.init;
-
-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.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Temporary class that tracks the result of the list builder and dumps it to text when requested.
- *
- * Eventually, this will be something that hands off the result of the pipeline to the View layer.
- */
-public class FakePipelineConsumer implements Dumpable {
- private List<ListEntry> mEntries = Collections.emptyList();
-
- /** Attach the consumer to the pipeline. */
- public void attach(ShadeListBuilder listBuilder) {
- listBuilder.setOnRenderListListener(this::onBuildComplete);
- }
-
- private void onBuildComplete(List<ListEntry> entries) {
- mEntries = entries;
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println();
- pw.println("Active notif tree:");
- for (int i = 0; i < mEntries.size(); i++) {
- ListEntry entry = mEntries.get(i);
- if (entry instanceof GroupEntry) {
- GroupEntry ge = (GroupEntry) entry;
- pw.println(dumpGroup(ge, "", i));
-
- pw.println(dumpEntry(ge.getSummary(), INDENT, -1));
- for (int j = 0; j < ge.getChildren().size(); j++) {
- pw.println(dumpEntry(ge.getChildren().get(j), INDENT, j));
- }
- } else {
- pw.println(dumpEntry(entry.getRepresentativeEntry(), "", i));
- }
- }
- }
-
- private String dumpGroup(GroupEntry entry, String indent, int index) {
- return String.format(
- "%s[%d] %s (group)",
- indent,
- index,
- entry.getKey());
- }
-
- private String dumpEntry(NotificationEntry entry, String indent, int index) {
- return String.format(
- "%s[%s] %s (channel=%s)",
- indent,
- index == -1 ? "*" : Integer.toString(index),
- entry.getKey(),
- entry.getChannel() != null ? entry.getChannel().getId() : "");
- }
-
- private static final String INDENT = " ";
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
index 258f6d0..f150257 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
@@ -25,10 +25,12 @@
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.NotifViewManager;
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.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -50,7 +52,7 @@
private final DumpManager mDumpManager;
private final FeatureFlags mFeatureFlags;
- private final FakePipelineConsumer mFakePipelineConsumer = new FakePipelineConsumer();
+ private final NotifViewManager mNotifViewManager;
@Inject
public NotifPipelineInitializer(
@@ -61,7 +63,8 @@
NotifCoordinators notifCoordinators,
NotifInflaterImpl notifInflater,
DumpManager dumpManager,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ NotifViewManager notifViewManager) {
mPipelineWrapper = pipelineWrapper;
mGroupCoalescer = groupCoalescer;
mNotifCollection = notifCollection;
@@ -70,12 +73,14 @@
mDumpManager = dumpManager;
mNotifInflater = notifInflater;
mFeatureFlags = featureFlags;
+ mNotifViewManager = notifViewManager;
}
/** Hooks the new pipeline up to NotificationManager */
public void initialize(
NotificationListener notificationService,
- NotificationRowBinderImpl rowBinder) {
+ NotificationRowBinderImpl rowBinder,
+ NotificationListContainer listContainer) {
mDumpManager.registerDumpable("NotifPipeline", this);
@@ -88,7 +93,8 @@
mNotifPluggableCoordinators.attach(mPipelineWrapper);
// Wire up pipeline
- mFakePipelineConsumer.attach(mListBuilder);
+ mNotifViewManager.setViewConsumer(listContainer);
+ mNotifViewManager.attach(mListBuilder);
mListBuilder.attach(mNotifCollection);
mNotifCollection.attach(mGroupCoalescer);
mGroupCoalescer.attach(notificationService);
@@ -98,7 +104,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mFakePipelineConsumer.dump(fd, pw, args);
+ mNotifViewManager.dump(fd, pw, args);
mNotifPluggableCoordinators.dump(fd, pw, args);
mGroupCoalescer.dump(fd, pw, args);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index 8a6d5c7..7a7178c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -94,7 +94,10 @@
notifBindPipelineInitializer.initialize()
if (featureFlags.isNewNotifPipelineEnabled) {
- newNotifPipeline.get().initialize(notificationListener, notificationRowBinder)
+ newNotifPipeline.get().initialize(
+ notificationListener,
+ notificationRowBinder,
+ listContainer)
}
if (featureFlags.isNewNotifPipelineRenderingEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index ea1bdd6..b9dd974 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -271,6 +271,10 @@
}
}
+ public boolean isActive() {
+ return mActivated;
+ }
+
private void startActivateAnimation(final boolean reverse) {
if (!isAttachedToWindow()) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
index 2643ec9..2f0e433 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
@@ -111,7 +111,7 @@
if (mNeedsDimming && ev.getActionMasked() == MotionEvent.ACTION_DOWN
&& mView.disallowSingleClick(ev)
&& !mAccessibilityManager.isTouchExplorationEnabled()) {
- if (!mView.isActivated()) {
+ if (!mView.isActive()) {
return true;
} else if (!mDoubleTapHelper.isWithinDoubleTapSlop(ev)) {
mBlockNextTouch = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index b1db5b5..5f2b256 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -94,6 +94,7 @@
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
+import com.android.systemui.statusbar.notification.stack.NotificationListItem;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.SwipeableView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -115,7 +116,8 @@
* the group summary (which contains 1 or more child notifications).
*/
public class ExpandableNotificationRow extends ActivatableNotificationView
- implements PluginListener<NotificationMenuRowPlugin>, SwipeableView {
+ implements PluginListener<NotificationMenuRowPlugin>, SwipeableView,
+ NotificationListItem {
private static final boolean DEBUG = false;
private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
@@ -666,6 +668,7 @@
layout.setHeights(minHeight, headsUpHeight, mNotificationMaxHeight);
}
+ @NonNull
public NotificationEntry getEntry() {
return mEntry;
}
@@ -767,6 +770,17 @@
row.setIsChildInGroup(true, this);
}
+ /**
+ * Same as {@link #addChildNotification(ExpandableNotificationRow, int)}, but takes a
+ * {@link NotificationListItem} instead
+ *
+ * @param childItem item
+ * @param childIndex index
+ */
+ public void addChildNotification(NotificationListItem childItem, int childIndex) {
+ addChildNotification((ExpandableNotificationRow) childItem.getView(), childIndex);
+ }
+
public void removeChildNotification(ExpandableNotificationRow row) {
if (mChildrenContainer != null) {
mChildrenContainer.removeNotification(row);
@@ -777,6 +791,11 @@
}
@Override
+ public void removeChildNotification(NotificationListItem child) {
+ removeChildNotification((ExpandableNotificationRow) child.getView());
+ }
+
+ @Override
public boolean isChildInGroup() {
return mNotificationParent != null;
}
@@ -879,7 +898,7 @@
* @param callback the callback to invoked in case it is not allowed
* @return whether the list order has changed
*/
- public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder,
+ public boolean applyChildOrder(List<? extends NotificationListItem> childOrder,
VisualStabilityManager visualStabilityManager,
VisualStabilityManager.Callback callback) {
return mChildrenContainer != null && mChildrenContainer.applyChildOrder(childOrder,
@@ -1274,6 +1293,11 @@
onChildrenCountChanged();
}
+ @Override
+ public View getView() {
+ return this;
+ }
+
public void setForceUnlocked(boolean forceUnlocked) {
mForceUnlocked = forceUnlocked;
if (mIsSummaryWithChildren) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
index 1e2571b5..162786c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
@@ -40,6 +40,7 @@
private var conversationIcon: View? = null
private var conversationBadge: View? = null
private var expandButton: View? = null
+ private lateinit var expandButtonContainer: View
private var messagingLinearLayout: MessagingLinearLayout? = null
init {
@@ -56,6 +57,8 @@
com.android.internal.R.id.conversation_icon_badge)
expandButton = conversationLayout.requireViewById(
com.android.internal.R.id.expand_button)
+ expandButtonContainer = conversationLayout.requireViewById(
+ com.android.internal.R.id.expand_button_container)
}
override fun onContentUpdated(row: ExpandableNotificationRow) {
@@ -90,6 +93,14 @@
conversationLayout.updateExpandability(expandable, onClickListener)
}
+ override fun disallowSingleClick(x: Float, y: Float): Boolean {
+ if (expandButtonContainer.visibility == View.VISIBLE
+ && isOnView(expandButtonContainer, x, y)) {
+ return true
+ }
+ return super.disallowSingleClick(x, y)
+ }
+
override fun getMinLayoutHeight(): Int {
if (mActionsContainer != null && mActionsContainer.visibility != View.GONE) {
return minHeightWithActions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
index d41f5af..2d99ab1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -58,7 +58,6 @@
private TextView mText;
protected View mActionsContainer;
private ImageView mReplyAction;
- private Rect mTmpRect = new Rect();
private int mContentHeight;
private int mMinHeightHint;
@@ -271,18 +270,6 @@
return super.disallowSingleClick(x, y);
}
- private boolean isOnView(View view, float x, float y) {
- View searchView = (View) view.getParent();
- while (searchView != null && !(searchView instanceof ExpandableNotificationRow)) {
- searchView.getHitRect(mTmpRect);
- x -= mTmpRect.left;
- y -= mTmpRect.top;
- searchView = (View) searchView.getParent();
- }
- view.getHitRect(mTmpRect);
- return mTmpRect.contains((int) x,(int) y);
- }
-
@Override
public void onContentUpdated(ExpandableNotificationRow row) {
// Reinspect the notification. Before the super call, because the super call also updates
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index c834e4b..46d7d93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -24,6 +24,7 @@
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
+import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
@@ -49,6 +50,7 @@
protected final View mView;
protected final ExpandableNotificationRow mRow;
+ private final Rect mTmpRect = new Rect();
protected int mBackgroundColor = 0;
@@ -305,6 +307,26 @@
return false;
}
+ /**
+ * Is a given x and y coordinate on a view.
+ *
+ * @param view the view to be checked
+ * @param x the x coordinate, relative to the ExpandableNotificationRow
+ * @param y the y coordinate, relative to the ExpandableNotificationRow
+ * @return {@code true} if it is on the view
+ */
+ protected boolean isOnView(View view, float x, float y) {
+ View searchView = (View) view.getParent();
+ while (searchView != null && !(searchView instanceof ExpandableNotificationRow)) {
+ searchView.getHitRect(mTmpRect);
+ x -= mTmpRect.left;
+ y -= mTmpRect.top;
+ searchView = (View) searchView.getParent();
+ }
+ view.getHitRect(mTmpRect);
+ return mTmpRect.contains((int) x,(int) y);
+ }
+
public int getMinLayoutHeight() {
return 0;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index d7c88e3..2c17764 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -412,7 +412,7 @@
* @param callback
* @return whether the list order has changed
*/
- public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder,
+ public boolean applyChildOrder(List<? extends NotificationListItem> childOrder,
VisualStabilityManager visualStabilityManager,
VisualStabilityManager.Callback callback) {
if (childOrder == null) {
@@ -421,7 +421,7 @@
boolean result = false;
for (int i = 0; i < mChildren.size() && i < childOrder.size(); i++) {
ExpandableNotificationRow child = mChildren.get(i);
- ExpandableNotificationRow desiredChild = childOrder.get(i);
+ ExpandableNotificationRow desiredChild = (ExpandableNotificationRow) childOrder.get(i);
if (child != desiredChild) {
if (visualStabilityManager.canReorderNotification(desiredChild)) {
mChildren.remove(desiredChild);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
index 15cc72c..c4a720c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
@@ -18,12 +18,14 @@
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
+import android.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.SimpleNotificationListContainer;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -33,7 +35,7 @@
* notification views added and removed from it, and will manage displaying them to the user.
*/
public interface NotificationListContainer extends ExpandableView.OnHeightChangedListener,
- VisibilityLocationProvider {
+ VisibilityLocationProvider, SimpleNotificationListContainer {
/**
* Called when a child is being transferred.
@@ -186,4 +188,10 @@
}
default void setWillExpand(boolean willExpand) {};
+
+ /**
+ * Remove a list item from the container
+ * @param v the item to remove
+ */
+ void removeListItem(@NonNull NotificationListItem v);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListItem.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListItem.java
new file mode 100644
index 0000000..8991abe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListItem.java
@@ -0,0 +1,66 @@
+/*
+ * 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.stack;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.view.View;
+
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import java.util.List;
+
+/**
+* A NotificationListItem is a child view of the notification list that can yield a
+* NotificationEntry when asked. I.e., it's an ExpandableNotificationRow but doesn't require us
+* to strictly rely on ExpandableNotificationRow as our consumed type
+ */
+public interface NotificationListItem {
+ /** @return entry for this item */
+ @NonNull
+ NotificationEntry getEntry();
+
+ /** @return true if the blocking helper is showing */
+ boolean isBlockingHelperShowing();
+
+ /** @return true if this list item is a summary with children */
+ boolean isSummaryWithChildren();
+
+ // This generic is kind of ugly - we should change this once the old VHM is gone
+ /** @return list of the children of this item */
+ List<? extends NotificationListItem> getNotificationChildren();
+
+ /** remove all children from this list item */
+ void removeAllChildren();
+
+ /** remove particular child */
+ void removeChildNotification(NotificationListItem child);
+
+ /** add an item as a child */
+ void addChildNotification(NotificationListItem child, int childIndex);
+
+ /** Update the order of the children with the new list */
+ boolean applyChildOrder(
+ List<? extends NotificationListItem> childOrderList,
+ VisualStabilityManager vsm,
+ @Nullable VisualStabilityManager.Callback callback);
+
+ /** return the associated view for this list item */
+ @NonNull
+ View getView();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
index 42a7c6a..f6f8363 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
@@ -447,7 +447,6 @@
}
}
-
@VisibleForTesting
ExpandableView getGentleHeaderView() {
return mGentleHeader;
@@ -471,7 +470,7 @@
private final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
@Override
public void onLocaleListChanged() {
- mGentleHeader.reinflateContents();
+ reinflateViews(LayoutInflater.from(mParent.getContext()));
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index cfcbd88..4d4a2ded 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -3323,11 +3323,21 @@
}
@Override
+ public void notifyGroupChildRemoved(View child, ViewGroup parent) {
+ notifyGroupChildRemoved((ExpandableView) child, parent);
+ }
+
+ @Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void notifyGroupChildAdded(ExpandableView row) {
onViewAddedInternal(row);
}
+ @Override
+ public void notifyGroupChildAdded(View view) {
+ notifyGroupChildAdded((ExpandableView) view);
+ }
+
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
public void setAnimationsEnabled(boolean animationsEnabled) {
mAnimationsEnabled = animationsEnabled;
@@ -5137,11 +5147,22 @@
@Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
+ public void removeListItem(NotificationListItem v) {
+ removeContainerView(v.getView());
+ }
+
+ @Override
+ @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void addContainerView(View v) {
Assert.isMainThread();
addView(v);
}
+ @Override
+ public void addListItem(NotificationListItem v) {
+ addContainerView(v.getView());
+ }
+
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void runAfterAnimationFinished(Runnable runnable) {
mAnimationFinishedRunnables.add(runnable);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
index 1b4f98f..bc25c71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
@@ -76,9 +76,7 @@
}
}
- override fun needsClippingToShelf(): Boolean {
- return true
- }
+ override fun needsClippingToShelf(): Boolean = true
override fun applyContentTransformation(contentAlpha: Float, translationY: Float) {
super.applyContentTransformation(contentAlpha, translationY)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
index deb5532..a3d8eec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
@@ -20,7 +20,6 @@
import android.annotation.StringRes;
import android.content.Context;
import android.util.AttributeSet;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -30,16 +29,17 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
-import java.util.Objects;
-
/**
- * Similar in size and appearance to the NotificationShelf, appears at the beginning of some
- * notification sections. Currently only used for gentle notifications.
+ * Header displayed above a notification section in the shade. Currently used for Alerting and
+ * Silent sections.
*/
public class SectionHeaderView extends StackScrollerDecorView {
+
private ViewGroup mContents;
private TextView mLabelView;
private ImageView mClearAllButton;
+ @StringRes @Nullable private Integer mLabelTextId;
+ @Nullable private View.OnClickListener mLabelClickListener = null;
@Nullable private View.OnClickListener mOnClearClickListener = null;
public SectionHeaderView(Context context, AttributeSet attrs) {
@@ -48,18 +48,24 @@
@Override
protected void onFinishInflate() {
- mContents = Objects.requireNonNull(findViewById(R.id.content));
+ mContents = requireViewById(R.id.content);
bindContents();
super.onFinishInflate();
setVisible(true /* nowVisible */, false /* animate */);
}
private void bindContents() {
- mLabelView = Objects.requireNonNull(findViewById(R.id.header_label));
- mClearAllButton = Objects.requireNonNull(findViewById(R.id.btn_clear_all));
+ mLabelView = requireViewById(R.id.header_label);
+ mClearAllButton = requireViewById(R.id.btn_clear_all);
if (mOnClearClickListener != null) {
mClearAllButton.setOnClickListener(mOnClearClickListener);
}
+ if (mLabelClickListener != null) {
+ mLabelView.setOnClickListener(mLabelClickListener);
+ }
+ if (mLabelTextId != null) {
+ mLabelView.setText(mLabelTextId);
+ }
}
@Override
@@ -72,21 +78,6 @@
return null;
}
- /**
- * Destroys and reinflates the visible contents of the section header. For use on configuration
- * changes or any other time that layout values might need to be re-evaluated.
- *
- * Does not reinflate the base content view itself ({@link #findContentView()} or any of the
- * decorator views, such as the background view or shadow view.
- */
- void reinflateContents() {
- mContents.removeAllViews();
- LayoutInflater.from(getContext()).inflate(
- R.layout.status_bar_notification_section_header_contents,
- mContents);
- bindContents();
- }
-
@Override
public boolean isTransparent() {
return true;
@@ -105,6 +96,7 @@
* Fired whenever the user clicks on the body of the header (e.g. no sub-buttons or anything).
*/
void setOnHeaderClickListener(View.OnClickListener listener) {
+ mLabelClickListener = listener;
mLabelView.setOnClickListener(listener);
}
@@ -129,6 +121,7 @@
}
void setHeaderText(@StringRes int resId) {
+ mLabelTextId = resId;
mLabelView.setText(resId);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index c282cb8..0b747f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -114,8 +114,9 @@
mInitialTouchY = y;
int startHeight = (int) (mPickedChild.getActualHeight()
+ mPickedChild.getTranslationY());
- mPanel.setPanelScrimMinFraction((float) startHeight
- / mPanel.getMaxPanelHeight());
+ float maxPanelHeight = mPanel.getMaxPanelHeight();
+ mPanel.setPanelScrimMinFraction(maxPanelHeight > 0f
+ ? (float) startHeight / maxPanelHeight : 0f);
mPanel.startExpandMotion(x, y, true /* startTracking */, startHeight);
mPanel.startExpandingFromPeek();
// This call needs to be after the expansion start otherwise we will get a
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index 77337e9..ccf6707 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -398,8 +398,7 @@
NotificationGroup group = mGroupMap.get(groupKey);
//TODO: see if this can become an Entry
return group == null ? null
- : group.summary == null ? null
- : group.summary;
+ : group.summary;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index c61d7bb..f9726d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -1844,7 +1844,14 @@
} else {
maxHeight = calculatePanelHeightShade();
}
- maxHeight = Math.max(maxHeight, min);
+ maxHeight = Math.max(min, maxHeight);
+ if (maxHeight == 0) {
+ Log.wtf(TAG, "maxPanelHeight is 0. getOverExpansionAmount(): "
+ + getOverExpansionAmount() + ", calculatePanelHeightQsExpanded: "
+ + calculatePanelHeightQsExpanded() + ", calculatePanelHeightShade: "
+ + calculatePanelHeightShade() + ", mStatusBarMinHeight = "
+ + mStatusBarMinHeight + ", mQsMinExpansionHeight = " + mQsMinExpansionHeight);
+ }
return maxHeight;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 8d8c8da..c106518 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone;
+import static java.lang.Float.isNaN;
+
import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
@@ -161,6 +163,9 @@
* fraction as the panel also might be expanded if the fraction is 0
*/
public void panelExpansionChanged(float frac, boolean expanded) {
+ if (isNaN(frac)) {
+ throw new IllegalArgumentException("frac cannot be NaN");
+ }
boolean fullyClosed = true;
boolean fullyOpened = false;
if (SPEW) LOG("panelExpansionChanged: start state=%d", mState);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index e25c14c..1c1e7c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -18,6 +18,8 @@
import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection;
+import static java.lang.Float.isNaN;
+
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
@@ -254,6 +256,9 @@
@Override
public void panelScrimMinFractionChanged(float minFraction) {
+ if (isNaN(minFraction)) {
+ throw new IllegalArgumentException("minFraction cannot be NaN");
+ }
if (mMinFraction != minFraction) {
mMinFraction = minFraction;
updateScrimFraction();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 24b9685..a81189e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -53,6 +53,16 @@
boolean isAodPowerSave();
/**
+ * Returns {@code true} if reverse is supported.
+ */
+ default boolean isReverseSupported() { return false; }
+
+ /**
+ * Returns {@code true} if reverse is on.
+ */
+ default boolean isReverseOn() { return false; }
+
+ /**
* Set reverse state.
* @param isReverse true if turn on reverse, false otherwise
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 7d532a8..38c165b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -65,7 +65,6 @@
new TetheringManager.TetheringEventCallback() {
@Override
public void onTetheringSupported(boolean supported) {
- super.onTetheringSupported(supported);
if (mIsTetheringSupported != supported) {
mIsTetheringSupported = supported;
fireHotspotAvailabilityChanged();
@@ -75,7 +74,6 @@
@Override
public void onTetherableInterfaceRegexpsChanged(
TetheringManager.TetheringInterfaceRegexps reg) {
- super.onTetherableInterfaceRegexpsChanged(reg);
final boolean newValue = reg.getTetherableWifiRegexs().size() != 0;
if (mHasTetherableWifiRegexs != newValue) {
mHasTetherableWifiRegexs = newValue;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index a36f2c7..bb2eea9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -31,6 +31,7 @@
import androidx.test.InstrumentationRegistry;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.FalsingManager;
@@ -80,6 +81,9 @@
// None of them actually need it.
mDependency.injectTestDependency(FalsingManager.class, new FalsingManagerFake());
mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
+
+ // TODO: b/151614195 investigate root cause of needing this mock dependency
+ mDependency.injectMockDependency(LocalBluetoothManager.class);
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
index c25d4e2..2ff2b2a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
@@ -207,6 +207,56 @@
}
@Test
+ fun testBindAndLoadSuggested() {
+ val callback = object : ControlsBindingController.LoadCallback {
+ override fun error(message: String) {}
+
+ override fun accept(t: List<Control>) {}
+ }
+ controller.bindAndLoadSuggested(TEST_COMPONENT_NAME_1, callback)
+
+ verify(providers[0]).maybeBindAndLoadSuggested(any())
+ }
+
+ @Test
+ fun testLoadSuggested_onCompleteRemovesTimeout() {
+ val callback = object : ControlsBindingController.LoadCallback {
+ override fun error(message: String) {}
+
+ override fun accept(t: List<Control>) {}
+ }
+ val subscription = mock(IControlsSubscription::class.java)
+
+ controller.bindAndLoadSuggested(TEST_COMPONENT_NAME_1, callback)
+
+ verify(providers[0]).maybeBindAndLoadSuggested(capture(subscriberCaptor))
+ val b = Binder()
+ subscriberCaptor.value.onSubscribe(b, subscription)
+
+ subscriberCaptor.value.onComplete(b)
+ verify(providers[0]).cancelLoadTimeout()
+ }
+
+ @Test
+ fun testLoadSuggested_onErrorRemovesTimeout() {
+ val callback = object : ControlsBindingController.LoadCallback {
+ override fun error(message: String) {}
+
+ override fun accept(t: List<Control>) {}
+ }
+ val subscription = mock(IControlsSubscription::class.java)
+
+ controller.bindAndLoadSuggested(TEST_COMPONENT_NAME_1, callback)
+
+ verify(providers[0]).maybeBindAndLoadSuggested(capture(subscriberCaptor))
+ val b = Binder()
+ subscriberCaptor.value.onSubscribe(b, subscription)
+
+ subscriberCaptor.value.onError(b, "")
+ verify(providers[0]).cancelLoadTimeout()
+ }
+
+ @Test
fun testBindService() {
controller.bindService(TEST_COMPONENT_NAME_1)
executor.runAllReady()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index f9c9815..971d14c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -80,6 +80,10 @@
@Captor
private lateinit var structureInfoCaptor: ArgumentCaptor<StructureInfo>
+
+ @Captor
+ private lateinit var booleanConsumer: ArgumentCaptor<Consumer<Boolean>>
+
@Captor
private lateinit var controlLoadCallbackCaptor:
ArgumentCaptor<ControlsBindingController.LoadCallback>
@@ -155,9 +159,13 @@
verify(listingController).addCallback(capture(listingCallbackCaptor))
}
- private fun builderFromInfo(controlInfo: ControlInfo): Control.StatelessBuilder {
+ private fun builderFromInfo(
+ controlInfo: ControlInfo,
+ structure: CharSequence = ""
+ ): Control.StatelessBuilder {
return Control.StatelessBuilder(controlInfo.controlId, pendingIntent)
.setDeviceType(controlInfo.deviceType).setTitle(controlInfo.controlTitle)
+ .setStructure(structure)
}
@Test
@@ -746,4 +754,70 @@
inOrder.verify(persistenceWrapper).readFavorites()
inOrder.verify(listingController).addCallback(listingCallbackCaptor.value)
}
+
+ @Test
+ fun testSeedFavoritesForComponent() {
+ var succeeded = false
+ val control = builderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure).build()
+
+ controller.seedFavoritesForComponent(TEST_COMPONENT, Consumer { accepted ->
+ succeeded = accepted
+ })
+
+ verify(bindingController).bindAndLoadSuggested(eq(TEST_COMPONENT),
+ capture(controlLoadCallbackCaptor))
+
+ controlLoadCallbackCaptor.value.accept(listOf(control))
+
+ delayableExecutor.runAllReady()
+
+ assertEquals(listOf(TEST_STRUCTURE_INFO),
+ controller.getFavoritesForComponent(TEST_COMPONENT))
+ assertTrue(succeeded)
+ }
+
+ @Test
+ fun testSeedFavoritesForComponent_error() {
+ var succeeded = false
+
+ controller.seedFavoritesForComponent(TEST_COMPONENT, Consumer { accepted ->
+ succeeded = accepted
+ })
+
+ verify(bindingController).bindAndLoadSuggested(eq(TEST_COMPONENT),
+ capture(controlLoadCallbackCaptor))
+
+ controlLoadCallbackCaptor.value.error("Error loading")
+
+ delayableExecutor.runAllReady()
+
+ assertEquals(listOf<StructureInfo>(), controller.getFavoritesForComponent(TEST_COMPONENT))
+ assertFalse(succeeded)
+ }
+
+ @Test
+ fun testSeedFavoritesForComponent_inProgressCallback() {
+ var succeeded = false
+ var seeded = false
+ val control = builderFromInfo(TEST_CONTROL_INFO, TEST_STRUCTURE_INFO.structure).build()
+
+ controller.seedFavoritesForComponent(TEST_COMPONENT, Consumer { accepted ->
+ succeeded = accepted
+ })
+
+ verify(bindingController).bindAndLoadSuggested(eq(TEST_COMPONENT),
+ capture(controlLoadCallbackCaptor))
+
+ controller.addSeedingFavoritesCallback(Consumer { accepted ->
+ seeded = accepted
+ })
+ controlLoadCallbackCaptor.value.accept(listOf(control))
+
+ delayableExecutor.runAllReady()
+
+ assertEquals(listOf(TEST_STRUCTURE_INFO),
+ controller.getFavoritesForComponent(TEST_COMPONENT))
+ assertTrue(succeeded)
+ assertTrue(seeded)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
index cd82844..789d6df 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
@@ -92,6 +92,22 @@
}
@Test
+ fun testLoadSuggested_happyPath() {
+ val result = wrapper.loadSuggested(subscriber)
+
+ assertTrue(result)
+ verify(service).loadSuggested(subscriber)
+ }
+
+ @Test
+ fun testLoadSuggested_error() {
+ `when`(service.loadSuggested(any())).thenThrow(exception)
+ val result = wrapper.loadSuggested(subscriber)
+
+ assertFalse(result)
+ }
+
+ @Test
fun testSubscribe_happyPath() {
val list = listOf("TEST_ID")
val result = wrapper.subscribe(list, subscriber)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt
index ff5c8d4..267520e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt
@@ -59,13 +59,15 @@
private lateinit var scs: StatefulControlSubscriber
+ private val REQUEST_LIMIT = 5L
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
`when`(provider.componentName).thenReturn(TEST_COMPONENT)
`when`(provider.token).thenReturn(token)
- scs = StatefulControlSubscriber(controller, provider, executor)
+ scs = StatefulControlSubscriber(controller, provider, executor, REQUEST_LIMIT)
}
@Test
@@ -73,7 +75,7 @@
scs.onSubscribe(token, subscription)
executor.runAllReady()
- verify(provider).startSubscription(subscription)
+ verify(provider).startSubscription(subscription, REQUEST_LIMIT)
}
@Test
@@ -81,7 +83,7 @@
scs.onSubscribe(badToken, subscription)
executor.runAllReady()
- verify(provider, never()).startSubscription(subscription)
+ verify(provider, never()).startSubscription(subscription, REQUEST_LIMIT)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchHandlerTest.java
new file mode 100644
index 0000000..4d7e6ae
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchHandlerTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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.pip.phone;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.IActivityManager;
+import android.app.IActivityTaskManager;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.util.Size;
+import android.view.DisplayInfo;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.pip.PipBoundsHandler;
+import com.android.systemui.pip.PipSnapAlgorithm;
+import com.android.systemui.pip.PipTaskOrganizer;
+import com.android.systemui.shared.system.InputConsumerController;
+import com.android.systemui.util.DeviceConfigProxy;
+import com.android.systemui.util.FloatingContentCoordinator;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests against {@link PipTouchHandler}, including but not limited to:
+ * - Update movement bounds based on new bounds
+ * - Update movement bounds based on IME/shelf
+ * - Update movement bounds to PipResizeHandler
+ */
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class PipTouchHandlerTest extends SysuiTestCase {
+ private static final int ROUNDING_ERROR_MARGIN = 10;
+ private static final float DEFAULT_ASPECT_RATIO = 1f;
+ private static final Rect EMPTY_CURRENT_BOUNDS = null;
+
+ private PipTouchHandler mPipTouchHandler;
+ private DisplayInfo mDefaultDisplayInfo;
+
+ @Mock
+ private IActivityManager mActivityManager;
+
+ @Mock
+ private IActivityTaskManager mIActivityTaskManager;
+
+ @Mock
+ private PipMenuActivityController mPipMenuActivityController;
+
+ @Mock
+ private InputConsumerController mInputConsumerController;
+
+ @Mock
+ private PipBoundsHandler mPipBoundsHandler;
+
+ @Mock
+ private PipTaskOrganizer mPipTaskOrganizer;
+
+ @Mock
+ private FloatingContentCoordinator mFloatingContentCoordinator;
+
+ @Mock
+ private DeviceConfigProxy mDeviceConfigProxy;
+
+
+ private PipSnapAlgorithm mPipSnapAlgorithm;
+ private PipMotionHelper mMotionHelper;
+ private PipResizeGestureHandler mPipResizeGestureHandler;
+
+ Rect mInsetBounds;
+ Rect mMinBounds;
+ Rect mCurBounds;
+ boolean mFromImeAdjustment;
+ boolean mFromShelfAdjustment;
+ int mDisplayRotation;
+
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mPipSnapAlgorithm = new PipSnapAlgorithm(mContext);
+ mPipTouchHandler = new PipTouchHandler(mContext, mActivityManager, mIActivityTaskManager,
+ mPipMenuActivityController, mInputConsumerController, mPipBoundsHandler,
+ mPipTaskOrganizer, mFloatingContentCoordinator, mDeviceConfigProxy,
+ mPipSnapAlgorithm);
+ mMotionHelper = Mockito.spy(mPipTouchHandler.getMotionHelper());
+ mPipResizeGestureHandler = Mockito.spy(mPipTouchHandler.getPipResizeGestureHandler());
+ mPipTouchHandler.setPipMotionHelper(mMotionHelper);
+ mPipTouchHandler.setPipResizeGestureHandler(mPipResizeGestureHandler);
+
+ // Assume a display of 1000 x 1000
+ // inset of 10
+ mInsetBounds = new Rect(10, 10, 990, 990);
+ // minBounds of 100x100 bottom right corner
+ mMinBounds = new Rect(890, 890, 990, 990);
+ mCurBounds = new Rect();
+ mFromImeAdjustment = false;
+ mFromShelfAdjustment = false;
+ mDisplayRotation = 0;
+ }
+
+ @Test
+ public void updateMovementBounds_minBounds() {
+ Rect expectedMinMovementBounds = new Rect();
+ mPipSnapAlgorithm.getMovementBounds(mMinBounds, mInsetBounds, expectedMinMovementBounds, 0);
+
+ mPipTouchHandler.onMovementBoundsChanged(mInsetBounds, mMinBounds, mCurBounds,
+ mFromImeAdjustment, mFromShelfAdjustment, mDisplayRotation);
+
+ assertEquals(expectedMinMovementBounds, mPipTouchHandler.mNormalMovementBounds);
+ verify(mPipResizeGestureHandler, times(1))
+ .updateMinSize(mMinBounds.width(), mMinBounds.height());
+ }
+
+ @Test
+ public void updateMovementBounds_maxBounds() {
+ Point displaySize = new Point();
+ mContext.getDisplay().getRealSize(displaySize);
+ Size maxSize = mPipSnapAlgorithm.getSizeForAspectRatio(1,
+ mContext.getResources().getDimensionPixelSize(
+ R.dimen.pip_expanded_shortest_edge_size), displaySize.x, displaySize.y);
+ Rect maxBounds = new Rect(0, 0, maxSize.getWidth(), maxSize.getHeight());
+ Rect expectedMaxMovementBounds = new Rect();
+ mPipSnapAlgorithm.getMovementBounds(maxBounds, mInsetBounds, expectedMaxMovementBounds, 0);
+
+ mPipTouchHandler.onMovementBoundsChanged(mInsetBounds, mMinBounds, mCurBounds,
+ mFromImeAdjustment, mFromShelfAdjustment, mDisplayRotation);
+
+ assertEquals(expectedMaxMovementBounds, mPipTouchHandler.mExpandedMovementBounds);
+ verify(mPipResizeGestureHandler, times(1))
+ .updateMaxSize(maxBounds.width(), maxBounds.height());
+ }
+
+ @Test
+ public void updateMovementBounds_withImeAdjustment_movesPip() {
+ mFromImeAdjustment = true;
+ mPipTouchHandler.onMovementBoundsChanged(mInsetBounds, mMinBounds, mCurBounds,
+ mFromImeAdjustment, mFromShelfAdjustment, mDisplayRotation);
+
+ verify(mMotionHelper, times(1)).animateToOffset(any(), anyInt());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
index ac30421..dbbbaac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
@@ -85,6 +85,8 @@
@Mock
private NotificationMediaManager mNotificationMediaManager;
@Mock
+ private Executor mForegroundExecutor;
+ @Mock
private Executor mBackgroundExecutor;
@Mock
private LocalBluetoothManager mLocalBluetoothManager;
@@ -97,7 +99,7 @@
mTestableLooper.runWithLooper(() -> {
mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
mQsPanel = new QSPanel(mContext, null, mDumpManager, mBroadcastDispatcher,
- mQSLogger, mNotificationMediaManager, mBackgroundExecutor,
+ mQSLogger, mNotificationMediaManager, mForegroundExecutor, mBackgroundExecutor,
mLocalBluetoothManager);
// Provides a parent with non-zero size for QSPanel
mParentView = new FrameLayout(mContext);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index 73f3ddd..95c3e5a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -86,7 +86,7 @@
@Mock
private StatusBarIconController mIconController;
@Mock
- private QSFactoryImpl mDefaultFactory;
+ private QSFactory mDefaultFactory;
@Mock
private PluginManager mPluginManager;
@Mock
@@ -295,7 +295,7 @@
private static class TestQSTileHost extends QSTileHost {
TestQSTileHost(Context context, StatusBarIconController iconController,
- QSFactoryImpl defaultFactory, Handler mainHandler, Looper bgLooper,
+ QSFactory defaultFactory, Handler mainHandler, Looper bgLooper,
PluginManager pluginManager, TunerService tunerService,
Provider<AutoTileManager> autoTiles, DumpManager dumpManager,
BroadcastDispatcher broadcastDispatcher, StatusBar statusBar, QSLogger qsLogger) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
index 58be50e..953198c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
@@ -30,7 +30,7 @@
import androidx.test.runner.AndroidJUnit4
import com.android.systemui.SysuiTestCase
import com.android.systemui.plugins.qs.QSTile
-import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.QSHost
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import org.junit.Assert.assertEquals
@@ -56,7 +56,7 @@
val TILE_SPEC = CustomTile.toSpec(componentName)
}
- @Mock private lateinit var mTileHost: QSTileHost
+ @Mock private lateinit var mTileHost: QSHost
@Mock private lateinit var mTileService: IQSTileService
@Mock private lateinit var mTileServices: TileServices
@Mock private lateinit var mTileServiceManager: TileServiceManager
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index cc5f149..83877f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -52,6 +52,7 @@
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.notification.stack.NotificationListItem;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -285,9 +286,15 @@
public void notifyGroupChildAdded(ExpandableView row) {}
@Override
+ public void notifyGroupChildAdded(View v) {}
+
+ @Override
public void notifyGroupChildRemoved(ExpandableView row, ViewGroup childrenContainer) {}
@Override
+ public void notifyGroupChildRemoved(View v, ViewGroup childrenContainer) {}
+
+ @Override
public void generateAddAnimation(ExpandableView child, boolean fromMoreCard) {}
@Override
@@ -313,12 +320,22 @@
}
@Override
+ public void removeListItem(NotificationListItem li) {
+ removeContainerView(li.getView());
+ }
+
+ @Override
public void addContainerView(View v) {
mLayout.addView(v);
mRows.add(v);
}
@Override
+ public void addListItem(NotificationListItem li) {
+ addContainerView(li.getView());
+ }
+
+ @Override
public void setMaxDisplayedNotifications(int maxNotifications) {
if (mMakeReentrantCallDuringSetMaxDisplayedNotifications) {
mViewHierarchyManager.onDynamicPrivacyChanged();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java
new file mode 100644
index 0000000..0c109c4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.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.coordinator;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.RemoteInputController;
+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.NotifPromoter;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class HeadsUpCoordinatorTest extends SysuiTestCase {
+
+ private HeadsUpCoordinator mCoordinator;
+
+ // captured listeners and pluggables:
+ private NotifCollectionListener mCollectionListener;
+ private NotifPromoter mNotifPromoter;
+ private NotifLifetimeExtender mNotifLifetimeExtender;
+ private OnHeadsUpChangedListener mOnHeadsUpChangedListener;
+ private NotifSection mNotifSection;
+
+ @Mock private NotifPipeline mNotifPipeline;
+ @Mock private HeadsUpManager mHeadsUpManager;
+ @Mock private NotificationRemoteInputManager mRemoteInputManager;
+ @Mock private RemoteInputController mRemoteInputController;
+ @Mock private NotifLifetimeExtender.OnEndLifetimeExtensionCallback mEndLifetimeExtension;
+
+ private NotificationEntry mEntry;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
+
+ mCoordinator = new HeadsUpCoordinator(
+ mHeadsUpManager,
+ mRemoteInputManager
+ );
+
+ mCoordinator.attach(mNotifPipeline);
+
+ // capture arguments:
+ ArgumentCaptor<NotifCollectionListener> notifCollectionCaptor =
+ ArgumentCaptor.forClass(NotifCollectionListener.class);
+ ArgumentCaptor<NotifPromoter> notifPromoterCaptor =
+ ArgumentCaptor.forClass(NotifPromoter.class);
+ ArgumentCaptor<NotifLifetimeExtender> notifLifetimeExtenderCaptor =
+ ArgumentCaptor.forClass(NotifLifetimeExtender.class);
+ ArgumentCaptor<OnHeadsUpChangedListener> headsUpChangedListenerCaptor =
+ ArgumentCaptor.forClass(OnHeadsUpChangedListener.class);
+
+ verify(mNotifPipeline).addCollectionListener(notifCollectionCaptor.capture());
+ verify(mNotifPipeline).addPromoter(notifPromoterCaptor.capture());
+ verify(mNotifPipeline).addNotificationLifetimeExtender(
+ notifLifetimeExtenderCaptor.capture());
+ verify(mHeadsUpManager).addListener(headsUpChangedListenerCaptor.capture());
+
+ mCollectionListener = notifCollectionCaptor.getValue();
+ mNotifPromoter = notifPromoterCaptor.getValue();
+ mNotifLifetimeExtender = notifLifetimeExtenderCaptor.getValue();
+ mOnHeadsUpChangedListener = headsUpChangedListenerCaptor.getValue();
+
+ mNotifSection = mCoordinator.getSection();
+ mNotifLifetimeExtender.setCallback(mEndLifetimeExtension);
+ mEntry = new NotificationEntryBuilder().build();
+ }
+
+ @Test
+ public void testPromotesCurrentHUN() {
+ // GIVEN the current HUN is set to mEntry
+ setCurrentHUN(mEntry);
+
+ // THEN only promote the current HUN, mEntry
+ assertTrue(mNotifPromoter.shouldPromoteToTopLevel(mEntry));
+ assertFalse(mNotifPromoter.shouldPromoteToTopLevel(new NotificationEntryBuilder().build()));
+ }
+
+ @Test
+ public void testIncludeInSectionCurrentHUN() {
+ // GIVEN the current HUN is set to mEntry
+ setCurrentHUN(mEntry);
+
+ // THEN only section the current HUN, mEntry
+ assertTrue(mNotifSection.isInSection(mEntry));
+ assertFalse(mNotifSection.isInSection(new NotificationEntryBuilder().build()));
+ }
+
+ @Test
+ public void testLifetimeExtendsCurrentHUN() {
+ // GIVEN there is a HUN, mEntry
+ setCurrentHUN(mEntry);
+
+ // THEN only the current HUN, mEntry, should be lifetimeExtended
+ assertTrue(mNotifLifetimeExtender.shouldExtendLifetime(mEntry, /* cancellationReason */ 0));
+ assertFalse(mNotifLifetimeExtender.shouldExtendLifetime(
+ new NotificationEntryBuilder().build(), /* cancellationReason */ 0));
+ }
+
+ @Test
+ public void testLifetimeExtensionEndsOnNewHUN() {
+ // GIVEN there was a HUN that was lifetime extended
+ setCurrentHUN(mEntry);
+ assertTrue(mNotifLifetimeExtender.shouldExtendLifetime(
+ mEntry, /* cancellation reason */ 0));
+
+ // WHEN there's a new HUN
+ NotificationEntry newHUN = new NotificationEntryBuilder().build();
+ setCurrentHUN(newHUN);
+
+ // THEN the old entry's lifetime extension should be cancelled
+ verify(mEndLifetimeExtension).onEndLifetimeExtension(mNotifLifetimeExtender, mEntry);
+ }
+
+ @Test
+ public void testLifetimeExtensionEndsOnNoHUNs() {
+ // GIVEN there was a HUN that was lifetime extended
+ setCurrentHUN(mEntry);
+ assertTrue(mNotifLifetimeExtender.shouldExtendLifetime(
+ mEntry, /* cancellation reason */ 0));
+
+ // WHEN there's no longer a HUN
+ setCurrentHUN(null);
+
+ // THEN the old entry's lifetime extension should be cancelled
+ verify(mEndLifetimeExtension).onEndLifetimeExtension(mNotifLifetimeExtender, mEntry);
+ }
+
+ @Test
+ public void testOnEntryRemovedRemovesHeadsUpNotification() {
+ // GIVEN the current HUN is mEntry
+ setCurrentHUN(mEntry);
+
+ // WHEN mEntry is removed from the notification collection
+ mCollectionListener.onEntryRemoved(mEntry, /* cancellation reason */ 0);
+ when(mRemoteInputController.isSpinning(any())).thenReturn(false);
+
+ // THEN heads up manager should remove the entry
+ verify(mHeadsUpManager).removeNotification(mEntry.getKey(), false);
+ }
+
+ private void setCurrentHUN(NotificationEntry entry) {
+ when(mHeadsUpManager.getTopEntry()).thenReturn(entry);
+ when(mHeadsUpManager.isAlerting(any())).thenReturn(false);
+ if (entry != null) {
+ when(mHeadsUpManager.isAlerting(entry.getKey())).thenReturn(true);
+ }
+ mOnHeadsUpChangedListener.onHeadsUpStateChanged(entry, entry != null);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
index 792b4d5..8143cf5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
@@ -20,8 +20,10 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
@@ -33,12 +35,15 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.NotifViewBarn;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
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.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import org.junit.Before;
import org.junit.Test;
@@ -73,6 +78,8 @@
@Mock private NotifPipeline mNotifPipeline;
@Mock private IStatusBarService mService;
@Mock private NotifInflaterImpl mNotifInflater;
+ @Mock private NotificationInterruptStateProvider mNotificationInterruptStateProvider;
+ @Mock private HeadsUpManager mHeadsUpManager;
@Before
public void setUp() {
@@ -86,7 +93,10 @@
mock(PreparationCoordinatorLogger.class),
mNotifInflater,
mErrorManager,
- mService);
+ mock(NotifViewBarn.class),
+ mService,
+ mNotificationInterruptStateProvider,
+ mHeadsUpManager);
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
mCoordinator.attach(mNotifPipeline);
@@ -170,4 +180,24 @@
// THEN it isn't filtered from shade list
assertFalse(mUninflatedFilter.shouldFilterOut(mEntry, 0));
}
+
+ @Test
+ public void testShowHUNOnInflationFinished() {
+ // WHEN a notification should HUN and its inflation is finished
+ when(mNotificationInterruptStateProvider.shouldHeadsUp(mEntry)).thenReturn(true);
+ mCallback.onInflationFinished(mEntry);
+
+ // THEN we tell the HeadsUpManager to show the notification
+ verify(mHeadsUpManager).showNotification(mEntry);
+ }
+
+ @Test
+ public void testNoHUNOnInflationFinished() {
+ // WHEN a notification shouldn't HUN and its inflation is finished
+ when(mNotificationInterruptStateProvider.shouldHeadsUp(mEntry)).thenReturn(false);
+ mCallback.onInflationFinished(mEntry);
+
+ // THEN we never tell the HeadsUpManager to show the notification
+ verify(mHeadsUpManager, never()).showNotification(mEntry);
+ }
}
diff --git a/packages/Tethering/common/TetheringLib/api/current.txt b/packages/Tethering/common/TetheringLib/api/current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/packages/Tethering/common/TetheringLib/api/module-lib-current.txt b/packages/Tethering/common/TetheringLib/api/module-lib-current.txt
new file mode 100644
index 0000000..e823e17
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/api/module-lib-current.txt
@@ -0,0 +1,129 @@
+// Signature format: 2.0
+package android.net {
+
+ public final class TetheredClient implements android.os.Parcelable {
+ ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int);
+ method public int describeContents();
+ method @NonNull public java.util.List<android.net.TetheredClient.AddressInfo> getAddresses();
+ method @NonNull public android.net.MacAddress getMacAddress();
+ method public int getTetheringType();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient> CREATOR;
+ }
+
+ public static final class TetheredClient.AddressInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.net.LinkAddress getAddress();
+ method @Nullable public String getHostname();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient.AddressInfo> CREATOR;
+ }
+
+ public final class TetheringConstants {
+ field public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
+ field public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
+ field public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
+ field public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
+ field public static final String EXTRA_SET_ALARM = "extraSetAlarm";
+ }
+
+ public class TetheringManager {
+ ctor public TetheringManager(@NonNull android.content.Context, @NonNull java.util.function.Supplier<android.os.IBinder>);
+ method public int getLastTetherError(@NonNull String);
+ method @NonNull public String[] getTetherableBluetoothRegexs();
+ method @NonNull public String[] getTetherableIfaces();
+ method @NonNull public String[] getTetherableUsbRegexs();
+ method @NonNull public String[] getTetherableWifiRegexs();
+ method @NonNull public String[] getTetheredIfaces();
+ method @NonNull public String[] getTetheringErroredIfaces();
+ method public boolean isTetheringSupported();
+ method public boolean isTetheringSupported(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
+ method public void requestLatestTetheringEntitlementResult(int, @NonNull android.os.ResultReceiver, boolean);
+ method @Deprecated public int setUsbTethering(boolean);
+ method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering();
+ method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int);
+ method @Deprecated public int tether(@NonNull String);
+ method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback);
+ method @Deprecated public int untether(@NonNull String);
+ field public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED";
+ field public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
+ field public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
+ field public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
+ field public static final String EXTRA_ERRORED_TETHER = "erroredArray";
+ field public static final int TETHERING_BLUETOOTH = 2; // 0x2
+ field public static final int TETHERING_ETHERNET = 5; // 0x5
+ field public static final int TETHERING_INVALID = -1; // 0xffffffff
+ field public static final int TETHERING_NCM = 4; // 0x4
+ field public static final int TETHERING_USB = 1; // 0x1
+ field public static final int TETHERING_WIFI = 0; // 0x0
+ field public static final int TETHERING_WIFI_P2P = 3; // 0x3
+ field public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; // 0xc
+ field public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9; // 0x9
+ field public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8; // 0x8
+ field public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; // 0xd
+ field public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; // 0xa
+ field public static final int TETHER_ERROR_INTERNAL_ERROR = 5; // 0x5
+ field public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; // 0xf
+ field public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; // 0xe
+ field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
+ field public static final int TETHER_ERROR_PROVISIONING_FAILED = 11; // 0xb
+ field public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; // 0x2
+ field public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; // 0x6
+ field public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; // 0x4
+ field public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; // 0x1
+ field public static final int TETHER_ERROR_UNKNOWN_TYPE = 16; // 0x10
+ field public static final int TETHER_ERROR_UNSUPPORTED = 3; // 0x3
+ field public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; // 0x7
+ field public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2; // 0x2
+ field public static final int TETHER_HARDWARE_OFFLOAD_STARTED = 1; // 0x1
+ field public static final int TETHER_HARDWARE_OFFLOAD_STOPPED = 0; // 0x0
+ }
+
+ public static interface TetheringManager.OnTetheringEntitlementResultListener {
+ method public void onTetheringEntitlementResult(int);
+ }
+
+ public static interface TetheringManager.StartTetheringCallback {
+ method public default void onTetheringFailed(int);
+ method public default void onTetheringStarted();
+ }
+
+ public static interface TetheringManager.TetheringEventCallback {
+ method public default void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
+ method public default void onError(@NonNull String, int);
+ method public default void onOffloadStatusChanged(int);
+ method public default void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
+ method public default void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+ method public default void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+ method public default void onTetheringSupported(boolean);
+ method public default void onUpstreamChanged(@Nullable android.net.Network);
+ }
+
+ public static class TetheringManager.TetheringInterfaceRegexps {
+ method @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs();
+ method @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs();
+ method @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
+ }
+
+ public static class TetheringManager.TetheringRequest {
+ }
+
+ public static class TetheringManager.TetheringRequest.Builder {
+ ctor public TetheringManager.TetheringRequest.Builder(int);
+ method @NonNull public android.net.TetheringManager.TetheringRequest build();
+ method @Nullable public android.net.LinkAddress getClientStaticIpv4Address();
+ method @Nullable public android.net.LinkAddress getLocalIpv4Address();
+ method public boolean getShouldShowEntitlementUi();
+ method public int getTetheringType();
+ method public boolean isExemptFromEntitlementCheck();
+ method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setShouldShowEntitlementUi(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setStaticIpv4Addresses(@NonNull android.net.LinkAddress, @NonNull android.net.LinkAddress);
+ }
+
+}
+
diff --git a/packages/Tethering/common/TetheringLib/api/module-lib-removed.txt b/packages/Tethering/common/TetheringLib/api/module-lib-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/api/module-lib-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/packages/Tethering/common/TetheringLib/api/removed.txt b/packages/Tethering/common/TetheringLib/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/packages/Tethering/common/TetheringLib/api/system-current.txt b/packages/Tethering/common/TetheringLib/api/system-current.txt
new file mode 100644
index 0000000..3751135
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/api/system-current.txt
@@ -0,0 +1,100 @@
+// Signature format: 2.0
+package android.net {
+
+ public final class TetheredClient implements android.os.Parcelable {
+ ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int);
+ method public int describeContents();
+ method @NonNull public java.util.List<android.net.TetheredClient.AddressInfo> getAddresses();
+ method @NonNull public android.net.MacAddress getMacAddress();
+ method public int getTetheringType();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient> CREATOR;
+ }
+
+ public static final class TetheredClient.AddressInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.net.LinkAddress getAddress();
+ method @Nullable public String getHostname();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient.AddressInfo> CREATOR;
+ }
+
+ public class TetheringManager {
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering();
+ method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int);
+ method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback);
+ field public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED";
+ field public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
+ field public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
+ field public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
+ field public static final String EXTRA_ERRORED_TETHER = "erroredArray";
+ field public static final int TETHERING_BLUETOOTH = 2; // 0x2
+ field public static final int TETHERING_ETHERNET = 5; // 0x5
+ field public static final int TETHERING_INVALID = -1; // 0xffffffff
+ field public static final int TETHERING_NCM = 4; // 0x4
+ field public static final int TETHERING_USB = 1; // 0x1
+ field public static final int TETHERING_WIFI = 0; // 0x0
+ field public static final int TETHERING_WIFI_P2P = 3; // 0x3
+ field public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; // 0xc
+ field public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9; // 0x9
+ field public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8; // 0x8
+ field public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; // 0xd
+ field public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; // 0xa
+ field public static final int TETHER_ERROR_INTERNAL_ERROR = 5; // 0x5
+ field public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; // 0xf
+ field public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; // 0xe
+ field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
+ field public static final int TETHER_ERROR_PROVISIONING_FAILED = 11; // 0xb
+ field public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; // 0x2
+ field public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; // 0x6
+ field public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; // 0x4
+ field public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; // 0x1
+ field public static final int TETHER_ERROR_UNKNOWN_TYPE = 16; // 0x10
+ field public static final int TETHER_ERROR_UNSUPPORTED = 3; // 0x3
+ field public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; // 0x7
+ field public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2; // 0x2
+ field public static final int TETHER_HARDWARE_OFFLOAD_STARTED = 1; // 0x1
+ field public static final int TETHER_HARDWARE_OFFLOAD_STOPPED = 0; // 0x0
+ }
+
+ public static interface TetheringManager.OnTetheringEntitlementResultListener {
+ method public void onTetheringEntitlementResult(int);
+ }
+
+ public static interface TetheringManager.StartTetheringCallback {
+ method public default void onTetheringFailed(int);
+ method public default void onTetheringStarted();
+ }
+
+ public static interface TetheringManager.TetheringEventCallback {
+ method public default void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
+ method public default void onError(@NonNull String, int);
+ method public default void onOffloadStatusChanged(int);
+ method public default void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+ method public default void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+ method public default void onTetheringSupported(boolean);
+ method public default void onUpstreamChanged(@Nullable android.net.Network);
+ }
+
+ public static class TetheringManager.TetheringRequest {
+ }
+
+ public static class TetheringManager.TetheringRequest.Builder {
+ ctor public TetheringManager.TetheringRequest.Builder(int);
+ method @NonNull public android.net.TetheringManager.TetheringRequest build();
+ method @Nullable public android.net.LinkAddress getClientStaticIpv4Address();
+ method @Nullable public android.net.LinkAddress getLocalIpv4Address();
+ method public boolean getShouldShowEntitlementUi();
+ method public int getTetheringType();
+ method public boolean isExemptFromEntitlementCheck();
+ method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setShouldShowEntitlementUi(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setStaticIpv4Addresses(@NonNull android.net.LinkAddress, @NonNull android.net.LinkAddress);
+ }
+
+}
+
diff --git a/packages/Tethering/common/TetheringLib/api/system-removed.txt b/packages/Tethering/common/TetheringLib/api/system-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/api/system-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index 7f831ce..86ef7f0 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -115,6 +115,19 @@
*/
public static final String EXTRA_ERRORED_TETHER = "erroredArray";
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = false, value = {
+ TETHERING_WIFI,
+ TETHERING_USB,
+ TETHERING_BLUETOOTH,
+ TETHERING_WIFI_P2P,
+ TETHERING_NCM,
+ TETHERING_ETHERNET,
+ })
+ public @interface TetheringType {
+ }
+
/**
* Invalid tethering type.
* @see #startTethering.
@@ -158,22 +171,60 @@
*/
public static final int TETHERING_ETHERNET = 5;
- public static final int TETHER_ERROR_NO_ERROR = 0;
- public static final int TETHER_ERROR_UNKNOWN_IFACE = 1;
- public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2;
- public static final int TETHER_ERROR_UNSUPPORTED = 3;
- public static final int TETHER_ERROR_UNAVAIL_IFACE = 4;
- public static final int TETHER_ERROR_MASTER_ERROR = 5;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ TETHER_ERROR_NO_ERROR,
+ TETHER_ERROR_PROVISIONING_FAILED,
+ TETHER_ERROR_ENTITLEMENT_UNKNOWN,
+ })
+ public @interface EntitlementResult {
+ }
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ TETHER_ERROR_NO_ERROR,
+ TETHER_ERROR_UNKNOWN_IFACE,
+ TETHER_ERROR_SERVICE_UNAVAIL,
+ TETHER_ERROR_INTERNAL_ERROR,
+ TETHER_ERROR_TETHER_IFACE_ERROR,
+ TETHER_ERROR_ENABLE_FORWARDING_ERROR,
+ TETHER_ERROR_DISABLE_FORWARDING_ERROR,
+ TETHER_ERROR_IFACE_CFG_ERROR,
+ TETHER_ERROR_DHCPSERVER_ERROR,
+ })
+ public @interface TetheringIfaceError {
+ }
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ TETHER_ERROR_SERVICE_UNAVAIL,
+ TETHER_ERROR_INTERNAL_ERROR,
+ TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION,
+ TETHER_ERROR_UNKNOWN_TYPE,
+ })
+ public @interface StartTetheringError {
+ }
+
+ public static final int TETHER_ERROR_NO_ERROR = 0;
+ public static final int TETHER_ERROR_UNKNOWN_IFACE = 1;
+ public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2;
+ public static final int TETHER_ERROR_UNSUPPORTED = 3;
+ public static final int TETHER_ERROR_UNAVAIL_IFACE = 4;
+ public static final int TETHER_ERROR_INTERNAL_ERROR = 5;
public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6;
public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7;
- public static final int TETHER_ERROR_ENABLE_NAT_ERROR = 8;
- public static final int TETHER_ERROR_DISABLE_NAT_ERROR = 9;
- public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10;
- public static final int TETHER_ERROR_PROVISION_FAILED = 11;
- public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12;
+ public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8;
+ public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9;
+ public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10;
+ public static final int TETHER_ERROR_PROVISIONING_FAILED = 11;
+ public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12;
public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13;
public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14;
public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15;
+ public static final int TETHER_ERROR_UNKNOWN_TYPE = 16;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -508,23 +559,40 @@
private final TetheringRequestParcel mBuilderParcel;
/** Default constructor of Builder. */
- public Builder(final int type) {
+ public Builder(@TetheringType final int type) {
mBuilderParcel = new TetheringRequestParcel();
mBuilderParcel.tetheringType = type;
mBuilderParcel.localIPv4Address = null;
+ mBuilderParcel.staticClientAddress = null;
mBuilderParcel.exemptFromEntitlementCheck = false;
mBuilderParcel.showProvisioningUi = true;
}
/**
- * Configure tethering with static IPv4 assignment (with DHCP disabled).
+ * Configure tethering with static IPv4 assignment.
*
- * @param localIPv4Address The preferred local IPv4 address to use.
+ * The clientAddress must be in the localIPv4Address prefix. A DHCP server will be
+ * started, but will only be able to offer the client address. The two addresses must
+ * be in the same prefix.
+ *
+ * @param localIPv4Address The preferred local IPv4 link address to use.
+ * @param clientAddress The static client address.
*/
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
@NonNull
- public Builder useStaticIpv4Addresses(@NonNull final LinkAddress localIPv4Address) {
+ public Builder setStaticIpv4Addresses(@NonNull final LinkAddress localIPv4Address,
+ @NonNull final LinkAddress clientAddress) {
+ Objects.requireNonNull(localIPv4Address);
+ Objects.requireNonNull(clientAddress);
+ if (localIPv4Address.getPrefixLength() != clientAddress.getPrefixLength()
+ || !localIPv4Address.isIpv4() || !clientAddress.isIpv4()
+ || !new IpPrefix(localIPv4Address.toString()).equals(
+ new IpPrefix(clientAddress.toString()))) {
+ throw new IllegalArgumentException("Invalid server or client addresses");
+ }
+
mBuilderParcel.localIPv4Address = localIPv4Address;
+ mBuilderParcel.staticClientAddress = clientAddress;
return this;
}
@@ -536,11 +604,14 @@
return this;
}
- /** Start tethering without showing the provisioning UI. */
+ /**
+ * If an entitlement check is needed, sets whether to show the entitlement UI or to
+ * perform a silent entitlement check. By default, the entitlement UI is shown.
+ */
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
@NonNull
- public Builder setSilentProvisioning(boolean silent) {
- mBuilderParcel.showProvisioningUi = silent;
+ public Builder setShouldShowEntitlementUi(boolean showUi) {
+ mBuilderParcel.showProvisioningUi = showUi;
return this;
}
@@ -549,6 +620,33 @@
public TetheringRequest build() {
return new TetheringRequest(mBuilderParcel);
}
+
+ @Nullable
+ public LinkAddress getLocalIpv4Address() {
+ return mBuilderParcel.localIPv4Address;
+ }
+
+ /** Get static client address. */
+ @Nullable
+ public LinkAddress getClientStaticIpv4Address() {
+ return mBuilderParcel.staticClientAddress;
+ }
+
+ /** Get tethering type. */
+ @TetheringType
+ public int getTetheringType() {
+ return mBuilderParcel.tetheringType;
+ }
+
+ /** Check if exempt from entitlement check. */
+ public boolean isExemptFromEntitlementCheck() {
+ return mBuilderParcel.exemptFromEntitlementCheck;
+ }
+
+ /** Check if show entitlement ui. */
+ public boolean getShouldShowEntitlementUi() {
+ return mBuilderParcel.showProvisioningUi;
+ }
}
/**
@@ -563,6 +661,7 @@
public String toString() {
return "TetheringRequest [ type= " + mRequestParcel.tetheringType
+ ", localIPv4Address= " + mRequestParcel.localIPv4Address
+ + ", staticClientAddress= " + mRequestParcel.staticClientAddress
+ ", exemptFromEntitlementCheck= "
+ mRequestParcel.exemptFromEntitlementCheck + ", showProvisioningUi= "
+ mRequestParcel.showProvisioningUi + " ]";
@@ -572,18 +671,18 @@
/**
* Callback for use with {@link #startTethering} to find out whether tethering succeeded.
*/
- public abstract static class StartTetheringCallback {
+ public interface StartTetheringCallback {
/**
* Called when tethering has been successfully started.
*/
- public void onTetheringStarted() {}
+ default void onTetheringStarted() {}
/**
* Called when starting tethering failed.
*
- * @param resultCode One of the {@code TETHER_ERROR_*} constants.
+ * @param error The error that caused the failure.
*/
- public void onTetheringFailed(final int resultCode) {}
+ default void onTetheringFailed(@StartTetheringError final int error) {}
}
/**
@@ -654,7 +753,7 @@
android.Manifest.permission.TETHER_PRIVILEGED,
android.Manifest.permission.WRITE_SETTINGS
})
- public void stopTethering(final int type) {
+ public void stopTethering(@TetheringType final int type) {
final String callerPkg = mContext.getOpPackageName();
Log.i(TAG, "stopTethering caller:" + callerPkg);
@@ -679,10 +778,10 @@
*
* @param resultCode an int value of entitlement result. It may be one of
* {@link #TETHER_ERROR_NO_ERROR},
- * {@link #TETHER_ERROR_PROVISION_FAILED}, or
+ * {@link #TETHER_ERROR_PROVISIONING_FAILED}, or
* {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN}.
*/
- void onTetheringEntitlementResult(int resultCode);
+ void onTetheringEntitlementResult(@EntitlementResult int result);
}
/**
@@ -697,7 +796,8 @@
* fail if a tethering entitlement check is required.
*
* @param type the downstream type of tethering. Must be one of {@code #TETHERING_*} constants.
- * @param showEntitlementUi a boolean indicating whether to run UI-based entitlement check.
+ * @param showEntitlementUi a boolean indicating whether to check result for the UI-based
+ * entitlement check or the silent entitlement check.
* @param executor the executor on which callback will be invoked.
* @param listener an {@link OnTetheringEntitlementResultListener} which will be called to
* notify the caller of the result of entitlement check. The listener may be called zero
@@ -707,7 +807,8 @@
android.Manifest.permission.TETHER_PRIVILEGED,
android.Manifest.permission.WRITE_SETTINGS
})
- public void requestLatestTetheringEntitlementResult(int type, boolean showEntitlementUi,
+ public void requestLatestTetheringEntitlementResult(@TetheringType int type,
+ boolean showEntitlementUi,
@NonNull Executor executor,
@NonNull final OnTetheringEntitlementResultListener listener) {
if (listener == null) {
@@ -736,7 +837,7 @@
*/
// TODO: improve the usage of ResultReceiver, b/145096122
@SystemApi(client = MODULE_LIBRARIES)
- public void requestLatestTetheringEntitlementResult(final int type,
+ public void requestLatestTetheringEntitlementResult(@TetheringType final int type,
@NonNull final ResultReceiver receiver, final boolean showEntitlementUi) {
final String callerPkg = mContext.getOpPackageName();
Log.i(TAG, "getLatestTetheringEntitlementResult caller:" + callerPkg);
@@ -749,7 +850,7 @@
* Callback for use with {@link registerTetheringEventCallback} to find out tethering
* upstream status.
*/
- public abstract static class TetheringEventCallback {
+ public interface TetheringEventCallback {
/**
* Called when tethering supported status changed.
*
@@ -761,7 +862,7 @@
*
* @param supported The new supported status
*/
- public void onTetheringSupported(boolean supported) {}
+ default void onTetheringSupported(boolean supported) {}
/**
* Called when tethering upstream changed.
@@ -772,7 +873,7 @@
* @param network the {@link Network} of tethering upstream. Null means tethering doesn't
* have any upstream.
*/
- public void onUpstreamChanged(@Nullable Network network) {}
+ default void onUpstreamChanged(@Nullable Network network) {}
/**
* Called when there was a change in tethering interface regular expressions.
@@ -780,28 +881,30 @@
* <p>This will be called immediately after the callback is registered, and may be called
* multiple times later upon changes.
* @param reg The new regular expressions.
- * @deprecated Referencing interfaces by regular expressions is a deprecated mechanism.
+ *
+ * @hide
*/
- @Deprecated
- public void onTetherableInterfaceRegexpsChanged(@NonNull TetheringInterfaceRegexps reg) {}
+ @SystemApi(client = MODULE_LIBRARIES)
+ default void onTetherableInterfaceRegexpsChanged(@NonNull TetheringInterfaceRegexps reg) {}
/**
- * Called when there was a change in the list of tetherable interfaces.
+ * Called when there was a change in the list of tetherable interfaces. Tetherable
+ * interface means this interface is available and can be used for tethering.
*
* <p>This will be called immediately after the callback is registered, and may be called
* multiple times later upon changes.
- * @param interfaces The list of tetherable interfaces.
+ * @param interfaces The list of tetherable interface names.
*/
- public void onTetherableInterfacesChanged(@NonNull List<String> interfaces) {}
+ default void onTetherableInterfacesChanged(@NonNull List<String> interfaces) {}
/**
* Called when there was a change in the list of tethered interfaces.
*
* <p>This will be called immediately after the callback is registered, and may be called
* multiple times later upon changes.
- * @param interfaces The list of tethered interfaces.
+ * @param interfaces The list of 0 or more String of currently tethered interface names.
*/
- public void onTetheredInterfacesChanged(@NonNull List<String> interfaces) {}
+ default void onTetheredInterfacesChanged(@NonNull List<String> interfaces) {}
/**
* Called when an error occurred configuring tethering.
@@ -811,7 +914,7 @@
* @param ifName Name of the interface.
* @param error One of {@code TetheringManager#TETHER_ERROR_*}.
*/
- public void onError(@NonNull String ifName, int error) {}
+ default void onError(@NonNull String ifName, @TetheringIfaceError int error) {}
/**
* Called when the list of tethered clients changes.
@@ -824,7 +927,7 @@
* determine if they are still connected.
* @param clients The new set of tethered clients; the collection is not ordered.
*/
- public void onClientsChanged(@NonNull Collection<TetheredClient> clients) {}
+ default void onClientsChanged(@NonNull Collection<TetheredClient> clients) {}
/**
* Called when tethering offload status changes.
@@ -832,19 +935,20 @@
* <p>This will be called immediately after the callback is registered.
* @param status The offload status.
*/
- public void onOffloadStatusChanged(@TetherOffloadStatus int status) {}
+ default void onOffloadStatusChanged(@TetherOffloadStatus int status) {}
}
/**
* Regular expressions used to identify tethering interfaces.
- * @deprecated Referencing interfaces by regular expressions is a deprecated mechanism.
+ * @hide
*/
- @Deprecated
+ @SystemApi(client = MODULE_LIBRARIES)
public static class TetheringInterfaceRegexps {
private final String[] mTetherableBluetoothRegexs;
private final String[] mTetherableUsbRegexs;
private final String[] mTetherableWifiRegexs;
+ /** @hide */
public TetheringInterfaceRegexps(@NonNull String[] tetherableBluetoothRegexs,
@NonNull String[] tetherableUsbRegexs, @NonNull String[] tetherableWifiRegexs) {
mTetherableBluetoothRegexs = tetherableBluetoothRegexs.clone();
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl b/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl
index bf19d85f..c0280d3 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl
@@ -25,6 +25,7 @@
parcelable TetheringRequestParcel {
int tetheringType;
LinkAddress localIPv4Address;
+ LinkAddress staticClientAddress;
boolean exemptFromEntitlementCheck;
boolean showProvisioningUi;
}
diff --git a/packages/Tethering/res/values-mcc204-mnc04/strings.xml b/packages/Tethering/res/values-mcc204-mnc04/strings.xml
new file mode 100644
index 0000000..6bc2e2a
--- /dev/null
+++ b/packages/Tethering/res/values-mcc204-mnc04/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <!-- String for no upstream notification title [CHAR LIMIT=200] -->
+ <string name="no_upstream_notification_title">Tethering & Mobile Hotspot has no internet access</string>
+
+ <!-- String for cellular roaming notification title [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_title">Roaming</string>
+ <!-- String for cellular roaming notification message [CHAR LIMIT=500] -->
+ <string name="upstream_roaming_notification_message">You will be charged on a per MB basis for all data sent or received while using this service outside the Verizon Network. Please check our website for current international rates. To minimize charges, visit My Verizon periodically to monitor your usage, check your device settings to confirm which devices are connected, and consider using alternate data connections when available</string>
+ <!-- String for cellular roaming notification continue button [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_continue_button">Continue</string>
+</resources>
\ No newline at end of file
diff --git a/packages/Tethering/res/values-mcc310-mnc004/strings.xml b/packages/Tethering/res/values-mcc310-mnc004/strings.xml
new file mode 100644
index 0000000..6bc2e2a
--- /dev/null
+++ b/packages/Tethering/res/values-mcc310-mnc004/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <!-- String for no upstream notification title [CHAR LIMIT=200] -->
+ <string name="no_upstream_notification_title">Tethering & Mobile Hotspot has no internet access</string>
+
+ <!-- String for cellular roaming notification title [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_title">Roaming</string>
+ <!-- String for cellular roaming notification message [CHAR LIMIT=500] -->
+ <string name="upstream_roaming_notification_message">You will be charged on a per MB basis for all data sent or received while using this service outside the Verizon Network. Please check our website for current international rates. To minimize charges, visit My Verizon periodically to monitor your usage, check your device settings to confirm which devices are connected, and consider using alternate data connections when available</string>
+ <!-- String for cellular roaming notification continue button [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_continue_button">Continue</string>
+</resources>
\ No newline at end of file
diff --git a/packages/Tethering/res/values-mcc311-mnc480/strings.xml b/packages/Tethering/res/values-mcc311-mnc480/strings.xml
new file mode 100644
index 0000000..6bc2e2a
--- /dev/null
+++ b/packages/Tethering/res/values-mcc311-mnc480/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <!-- String for no upstream notification title [CHAR LIMIT=200] -->
+ <string name="no_upstream_notification_title">Tethering & Mobile Hotspot has no internet access</string>
+
+ <!-- String for cellular roaming notification title [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_title">Roaming</string>
+ <!-- String for cellular roaming notification message [CHAR LIMIT=500] -->
+ <string name="upstream_roaming_notification_message">You will be charged on a per MB basis for all data sent or received while using this service outside the Verizon Network. Please check our website for current international rates. To minimize charges, visit My Verizon periodically to monitor your usage, check your device settings to confirm which devices are connected, and consider using alternate data connections when available</string>
+ <!-- String for cellular roaming notification continue button [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_continue_button">Continue</string>
+</resources>
\ No newline at end of file
diff --git a/packages/Tethering/res/values/strings.xml b/packages/Tethering/res/values/strings.xml
index ba98a66..d50884b 100644
--- a/packages/Tethering/res/values/strings.xml
+++ b/packages/Tethering/res/values/strings.xml
@@ -32,4 +32,14 @@
Internet" settings page. That is currently the tether_settings_title_all string. -->
<!-- String for tether notification channel name [CHAR LIMIT=200] -->
<string name="notification_channel_tethering_status">Hotspot & tethering status</string>
+
+ <!-- String for no upstream notification title [CHAR LIMIT=200] -->
+ <string name="no_upstream_notification_title"></string>
+
+ <!-- String for cellular roaming notification title [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_title"></string>
+ <!-- String for cellular roaming notification message [CHAR LIMIT=500] -->
+ <string name="upstream_roaming_notification_message"></string>
+ <!-- String for cellular roaming notification continue button [CHAR LIMIT=200] -->
+ <string name="upstream_roaming_notification_continue_button"></string>
</resources>
\ No newline at end of file
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index 6c0c432..c5478d2 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -35,6 +35,7 @@
import android.net.RouteInfo;
import android.net.TetheredClient;
import android.net.TetheringManager;
+import android.net.TetheringRequestParcel;
import android.net.dhcp.DhcpLeaseParcelable;
import android.net.dhcp.DhcpServerCallbacks;
import android.net.dhcp.DhcpServingParamsParcel;
@@ -243,6 +244,10 @@
private IDhcpServer mDhcpServer;
private RaParams mLastRaParams;
private LinkAddress mIpv4Address;
+
+ private LinkAddress mStaticIpv4ServerAddr;
+ private LinkAddress mStaticIpv4ClientAddr;
+
@NonNull
private List<TetheredClient> mDhcpLeases = Collections.emptyList();
@@ -547,6 +552,8 @@
// into calls to InterfaceController, shared with startIPv4().
mInterfaceCtrl.clearIPv4Address();
mIpv4Address = null;
+ mStaticIpv4ServerAddr = null;
+ mStaticIpv4ClientAddr = null;
}
private boolean configureIPv4(boolean enabled) {
@@ -557,7 +564,10 @@
final Inet4Address srvAddr;
int prefixLen = 0;
try {
- if (mInterfaceType == TetheringManager.TETHERING_USB
+ if (mStaticIpv4ServerAddr != null) {
+ srvAddr = (Inet4Address) mStaticIpv4ServerAddr.getAddress();
+ prefixLen = mStaticIpv4ServerAddr.getPrefixLength();
+ } else if (mInterfaceType == TetheringManager.TETHERING_USB
|| mInterfaceType == TetheringManager.TETHERING_NCM) {
srvAddr = (Inet4Address) parseNumericAddress(USB_NEAR_IFACE_ADDR);
prefixLen = USB_PREFIX_LENGTH;
@@ -602,10 +612,6 @@
return false;
}
- if (!configureDhcp(enabled, srvAddr, prefixLen)) {
- return false;
- }
-
// Directly-connected route.
final IpPrefix ipv4Prefix = new IpPrefix(mIpv4Address.getAddress(),
mIpv4Address.getPrefixLength());
@@ -617,7 +623,8 @@
mLinkProperties.removeLinkAddress(mIpv4Address);
mLinkProperties.removeRoute(route);
}
- return true;
+
+ return configureDhcp(enabled, srvAddr, prefixLen);
}
private String getRandomWifiIPv4Address() {
@@ -937,6 +944,13 @@
mLinkProperties.setInterfaceName(mIfaceName);
}
+ private void maybeConfigureStaticIp(final TetheringRequestParcel request) {
+ if (request == null) return;
+
+ mStaticIpv4ServerAddr = request.localIPv4Address;
+ mStaticIpv4ClientAddr = request.staticClientAddress;
+ }
+
class InitialState extends State {
@Override
public void enter() {
@@ -951,9 +965,11 @@
mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
switch (message.arg1) {
case STATE_LOCAL_ONLY:
+ maybeConfigureStaticIp((TetheringRequestParcel) message.obj);
transitionTo(mLocalHotspotState);
break;
case STATE_TETHERED:
+ maybeConfigureStaticIp((TetheringRequestParcel) message.obj);
transitionTo(mTetheredState);
break;
default:
@@ -1038,7 +1054,7 @@
case CMD_START_TETHERING_ERROR:
case CMD_STOP_TETHERING_ERROR:
case CMD_SET_DNS_FORWARDERS_ERROR:
- mLastError = TetheringManager.TETHER_ERROR_MASTER_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
transitionTo(mInitialState);
break;
default:
@@ -1169,7 +1185,7 @@
} catch (RemoteException | ServiceSpecificException e) {
mLog.e("Exception enabling NAT: " + e.toString());
cleanupUpstream();
- mLastError = TetheringManager.TETHER_ERROR_ENABLE_NAT_ERROR;
+ mLastError = TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;
transitionTo(mInitialState);
return true;
}
diff --git a/packages/Tethering/src/android/net/util/TetheringUtils.java b/packages/Tethering/src/android/net/util/TetheringUtils.java
index 5a6d5c1..dd67ddd 100644
--- a/packages/Tethering/src/android/net/util/TetheringUtils.java
+++ b/packages/Tethering/src/android/net/util/TetheringUtils.java
@@ -15,8 +15,11 @@
*/
package android.net.util;
+import android.net.TetheringRequestParcel;
+
import java.io.FileDescriptor;
import java.net.SocketException;
+import java.util.Objects;
/**
* Native methods for tethering utilization.
@@ -38,4 +41,17 @@
public static int uint16(short s) {
return s & 0xffff;
}
+
+ /** Check whether two TetheringRequestParcels are the same. */
+ public static boolean isTetheringRequestEquals(final TetheringRequestParcel request,
+ final TetheringRequestParcel otherRequest) {
+ if (request == otherRequest) return true;
+
+ return request != null && otherRequest != null
+ && request.tetheringType == otherRequest.tetheringType
+ && Objects.equals(request.localIPv4Address, otherRequest.localIPv4Address)
+ && Objects.equals(request.staticClientAddress, otherRequest.staticClientAddress)
+ && request.exemptFromEntitlementCheck == otherRequest.exemptFromEntitlementCheck
+ && request.showProvisioningUi == otherRequest.showProvisioningUi;
+ }
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
index e81d6ac..bd60594f 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
@@ -25,7 +25,7 @@
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
-import static android.net.TetheringManager.TETHER_ERROR_PROVISION_FAILED;
+import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -579,7 +579,7 @@
switch (value) {
case TETHER_ERROR_ENTITLEMENT_UNKNOWN: return "TETHER_ERROR_ENTITLEMENT_UNKONWN";
case TETHER_ERROR_NO_ERROR: return "TETHER_ERROR_NO_ERROR";
- case TETHER_ERROR_PROVISION_FAILED: return "TETHER_ERROR_PROVISION_FAILED";
+ case TETHER_ERROR_PROVISIONING_FAILED: return "TETHER_ERROR_PROVISIONING_FAILED";
default:
return String.format("UNKNOWN ERROR (%d)", value);
}
@@ -592,7 +592,7 @@
protected void onReceiveResult(int resultCode, Bundle resultData) {
int updatedCacheValue = updateEntitlementCacheValue(type, resultCode);
addDownstreamMapping(type, updatedCacheValue);
- if (updatedCacheValue == TETHER_ERROR_PROVISION_FAILED && notifyFail) {
+ if (updatedCacheValue == TETHER_ERROR_PROVISIONING_FAILED && notifyFail) {
mListener.onUiEntitlementFailed(type);
}
if (receiver != null) receiver.send(updatedCacheValue, null);
@@ -635,8 +635,8 @@
mEntitlementCacheValue.put(type, resultCode);
return resultCode;
} else {
- mEntitlementCacheValue.put(type, TETHER_ERROR_PROVISION_FAILED);
- return TETHER_ERROR_PROVISION_FAILED;
+ mEntitlementCacheValue.put(type, TETHER_ERROR_PROVISIONING_FAILED);
+ return TETHER_ERROR_PROVISIONING_FAILED;
}
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
index a402ffa..15cdb6a 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
@@ -39,8 +39,7 @@
import android.net.netlink.ConntrackMessage;
import android.net.netlink.NetlinkConstants;
import android.net.netlink.NetlinkSocket;
-import android.net.netstats.provider.AbstractNetworkStatsProvider;
-import android.net.netstats.provider.NetworkStatsProviderCallback;
+import android.net.netstats.provider.NetworkStatsProvider;
import android.net.util.SharedLog;
import android.os.Handler;
import android.provider.Settings;
@@ -89,8 +88,8 @@
private final Handler mHandler;
private final OffloadHardwareInterface mHwInterface;
private final ContentResolver mContentResolver;
- private final @NonNull OffloadTetheringStatsProvider mStatsProvider;
- private final @Nullable NetworkStatsProviderCallback mStatsProviderCb;
+ @Nullable
+ private final OffloadTetheringStatsProvider mStatsProvider;
private final SharedLog mLog;
private final HashMap<String, LinkProperties> mDownstreams;
private boolean mConfigInitialized;
@@ -124,19 +123,18 @@
mHandler = h;
mHwInterface = hwi;
mContentResolver = contentResolver;
- mStatsProvider = new OffloadTetheringStatsProvider();
mLog = log.forSubComponent(TAG);
mDownstreams = new HashMap<>();
mExemptPrefixes = new HashSet<>();
mLastLocalPrefixStrs = new HashSet<>();
- NetworkStatsProviderCallback providerCallback = null;
+ OffloadTetheringStatsProvider provider = new OffloadTetheringStatsProvider();
try {
- providerCallback = nsm.registerNetworkStatsProvider(
- getClass().getSimpleName(), mStatsProvider);
+ nsm.registerNetworkStatsProvider(getClass().getSimpleName(), provider);
} catch (RuntimeException e) {
Log.wtf(TAG, "Cannot register offload stats provider: " + e);
+ provider = null;
}
- mStatsProviderCb = providerCallback;
+ mStatsProvider = provider;
}
/** Start hardware offload. */
@@ -185,7 +183,7 @@
// and we need to synchronize stats and limits between
// software and hardware forwarding.
updateStatsForAllUpstreams();
- mStatsProvider.pushTetherStats();
+ if (mStatsProvider != null) mStatsProvider.pushTetherStats();
}
@Override
@@ -198,7 +196,7 @@
// limits set take into account any software tethering
// traffic that has been happening in the meantime.
updateStatsForAllUpstreams();
- mStatsProvider.pushTetherStats();
+ if (mStatsProvider != null) mStatsProvider.pushTetherStats();
// [2] (Re)Push all state.
computeAndPushLocalPrefixes(UpdateType.FORCE);
pushAllDownstreamState();
@@ -217,10 +215,12 @@
// TODO: rev the HAL so that it provides an interface name.
updateStatsForCurrentUpstream();
- mStatsProvider.pushTetherStats();
- // Push stats to service does not cause the service react to it immediately.
- // Inform the service about limit reached.
- if (mStatsProviderCb != null) mStatsProviderCb.onLimitReached();
+ if (mStatsProvider != null) {
+ mStatsProvider.pushTetherStats();
+ // Push stats to service does not cause the service react to it
+ // immediately. Inform the service about limit reached.
+ mStatsProvider.notifyLimitReached();
+ }
}
@Override
@@ -263,13 +263,17 @@
}
@VisibleForTesting
- class OffloadTetheringStatsProvider extends AbstractNetworkStatsProvider {
+ class OffloadTetheringStatsProvider extends NetworkStatsProvider {
// These stats must only ever be touched on the handler thread.
@NonNull
private NetworkStats mIfaceStats = new NetworkStats(0L, 0);
@NonNull
private NetworkStats mUidStats = new NetworkStats(0L, 0);
+ /**
+ * A helper function that collect tether stats from local hashmap. Note that this does not
+ * invoke binder call.
+ */
@VisibleForTesting
@NonNull
NetworkStats getTetherStats(@NonNull StatsType how) {
@@ -280,14 +284,14 @@
final ForwardedStats value = kv.getValue();
final Entry entry = new Entry(kv.getKey(), uid, SET_DEFAULT, TAG_NONE, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_NO, value.rxBytes, 0L, value.txBytes, 0L, 0L);
- stats = stats.addValues(entry);
+ stats = stats.addEntry(entry);
}
return stats;
}
@Override
- public void setLimit(String iface, long quotaBytes) {
+ public void onSetLimit(String iface, long quotaBytes) {
// Listen for all iface is necessary since upstream might be changed after limit
// is set.
mHandler.post(() -> {
@@ -315,13 +319,12 @@
*/
public void pushTetherStats() {
// TODO: remove the accumulated stats and report the diff from HAL directly.
- if (null == mStatsProviderCb) return;
final NetworkStats ifaceDiff =
getTetherStats(StatsType.STATS_PER_IFACE).subtract(mIfaceStats);
final NetworkStats uidDiff =
getTetherStats(StatsType.STATS_PER_UID).subtract(mUidStats);
try {
- mStatsProviderCb.onStatsUpdated(0 /* token */, ifaceDiff, uidDiff);
+ notifyStatsUpdated(0 /* token */, ifaceDiff, uidDiff);
mIfaceStats = mIfaceStats.add(ifaceDiff);
mUidStats = mUidStats.add(uidDiff);
} catch (RuntimeException e) {
@@ -330,7 +333,7 @@
}
@Override
- public void requestStatsUpdate(int token) {
+ public void onRequestStatsUpdate(int token) {
// Do not attempt to update stats by querying the offload HAL
// synchronously from a different thread than the Handler thread. http://b/64771555.
mHandler.post(() -> {
@@ -340,7 +343,7 @@
}
@Override
- public void setAlert(long quotaBytes) {
+ public void onSetAlert(long quotaBytes) {
// TODO: Ask offload HAL to notify alert without stopping traffic.
}
}
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index 3d8dbab..8e2d4f4 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -39,11 +39,12 @@
import static android.net.TetheringManager.TETHERING_USB;
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
-import static android.net.TetheringManager.TETHER_ERROR_MASTER_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE;
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
+import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_TYPE;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
@@ -92,6 +93,7 @@
import android.net.util.InterfaceSet;
import android.net.util.PrefixUtils;
import android.net.util.SharedLog;
+import android.net.util.TetheringUtils;
import android.net.util.VersionedBroadcastListener;
import android.net.wifi.WifiClient;
import android.net.wifi.WifiManager;
@@ -196,6 +198,11 @@
private final SharedLog mLog = new SharedLog(TAG);
private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
new RemoteCallbackList<>();
+ // Currently active tethering requests per tethering type. Only one of each type can be
+ // requested at a time. After a tethering type is requested, the map keeps tethering parameters
+ // to be used after the interface comes up asynchronously.
+ private final SparseArray<TetheringRequestParcel> mActiveTetheringRequests =
+ new SparseArray<>();
// used to synchronize public access to members
private final Object mPublicSync;
@@ -487,14 +494,31 @@
}
void startTethering(final TetheringRequestParcel request, final IIntResultListener listener) {
- mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType,
- request.showProvisioningUi);
- enableTetheringInternal(request.tetheringType, true /* enabled */, listener);
+ mHandler.post(() -> {
+ final TetheringRequestParcel unfinishedRequest = mActiveTetheringRequests.get(
+ request.tetheringType);
+ // If tethering is already enabled with a different request,
+ // disable before re-enabling.
+ if (unfinishedRequest != null
+ && !TetheringUtils.isTetheringRequestEquals(unfinishedRequest, request)) {
+ enableTetheringInternal(request.tetheringType, false /* disabled */, null);
+ mEntitlementMgr.stopProvisioningIfNeeded(request.tetheringType);
+ }
+ mActiveTetheringRequests.put(request.tetheringType, request);
+
+ mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType,
+ request.showProvisioningUi);
+ enableTetheringInternal(request.tetheringType, true /* enabled */, listener);
+ });
}
void stopTethering(int type) {
- enableTetheringInternal(type, false /* disabled */, null);
- mEntitlementMgr.stopProvisioningIfNeeded(type);
+ mHandler.post(() -> {
+ mActiveTetheringRequests.remove(type);
+
+ enableTetheringInternal(type, false /* disabled */, null);
+ mEntitlementMgr.stopProvisioningIfNeeded(type);
+ });
}
/**
@@ -503,39 +527,45 @@
*/
private void enableTetheringInternal(int type, boolean enable,
final IIntResultListener listener) {
- int result;
+ int result = TETHER_ERROR_NO_ERROR;
switch (type) {
case TETHERING_WIFI:
result = setWifiTethering(enable);
- sendTetherResult(listener, result);
break;
case TETHERING_USB:
result = setUsbTethering(enable);
- sendTetherResult(listener, result);
break;
case TETHERING_BLUETOOTH:
setBluetoothTethering(enable, listener);
break;
case TETHERING_NCM:
result = setNcmTethering(enable);
- sendTetherResult(listener, result);
break;
case TETHERING_ETHERNET:
result = setEthernetTethering(enable);
- sendTetherResult(listener, result);
break;
default:
Log.w(TAG, "Invalid tether type.");
- sendTetherResult(listener, TETHER_ERROR_UNKNOWN_IFACE);
+ result = TETHER_ERROR_UNKNOWN_TYPE;
+ }
+
+ // The result of Bluetooth tethering will be sent by #setBluetoothTethering.
+ if (type != TETHERING_BLUETOOTH) {
+ sendTetherResult(listener, result, type);
}
}
- private void sendTetherResult(final IIntResultListener listener, int result) {
+ private void sendTetherResult(final IIntResultListener listener, final int result,
+ final int type) {
if (listener != null) {
try {
listener.onResult(result);
} catch (RemoteException e) { }
}
+
+ // If changing tethering fail, remove corresponding request
+ // no matter who trigger the start/stop.
+ if (result != TETHER_ERROR_NO_ERROR) mActiveTetheringRequests.remove(type);
}
private int setWifiTethering(final boolean enable) {
@@ -557,7 +587,7 @@
Binder.restoreCallingIdentity(ident);
}
- return TETHER_ERROR_MASTER_ERROR;
+ return TETHER_ERROR_INTERNAL_ERROR;
}
private void setBluetoothTethering(final boolean enable, final IIntResultListener listener) {
@@ -565,7 +595,7 @@
if (adapter == null || !adapter.isEnabled()) {
Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: "
+ (adapter == null));
- sendTetherResult(listener, TETHER_ERROR_SERVICE_UNAVAIL);
+ sendTetherResult(listener, TETHER_ERROR_SERVICE_UNAVAIL, TETHERING_BLUETOOTH);
return;
}
@@ -593,8 +623,8 @@
// We should figure out a way to bubble up that failure instead of sending success.
final int result = (((BluetoothPan) proxy).isTetheringOn() == enable)
? TETHER_ERROR_NO_ERROR
- : TETHER_ERROR_MASTER_ERROR;
- sendTetherResult(listener, result);
+ : TETHER_ERROR_INTERNAL_ERROR;
+ sendTetherResult(listener, result, TETHERING_BLUETOOTH);
adapter.closeProfileProxy(BluetoothProfile.PAN, proxy);
}
}, BluetoothProfile.PAN);
@@ -672,12 +702,18 @@
Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring");
return TETHER_ERROR_UNAVAIL_IFACE;
}
- // NOTE: If a CMD_TETHER_REQUESTED message is already in the TISM's
- // queue but not yet processed, this will be a no-op and it will not
- // return an error.
+ // NOTE: If a CMD_TETHER_REQUESTED message is already in the TISM's queue but not yet
+ // processed, this will be a no-op and it will not return an error.
//
- // TODO: reexamine the threading and messaging model.
- tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_REQUESTED, requestedState);
+ // This code cannot race with untether() because they both synchronize on mPublicSync.
+ // TODO: reexamine the threading and messaging model to totally remove mPublicSync.
+ final int type = tetherState.ipServer.interfaceType();
+ final TetheringRequestParcel request = mActiveTetheringRequests.get(type, null);
+ if (request != null) {
+ mActiveTetheringRequests.delete(type);
+ }
+ tetherState.ipServer.sendMessage(IpServer.CMD_TETHER_REQUESTED, requestedState, 0,
+ request);
return TETHER_ERROR_NO_ERROR;
}
}
@@ -2145,7 +2181,7 @@
// If TetherMasterSM is in ErrorState, TetherMasterSM stays there.
// Thus we give a chance for TetherMasterSM to recover to InitialState
// by sending CMD_CLEAR_ERROR
- if (error == TETHER_ERROR_MASTER_ERROR) {
+ if (error == TETHER_ERROR_INTERNAL_ERROR) {
mTetherMasterSM.sendMessage(TetherMasterSM.CMD_CLEAR_ERROR, who);
}
int which;
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
index 020b32a..c5329d8 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
@@ -33,6 +33,7 @@
import android.net.ITetheringEventCallback;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
+import android.net.NetworkStack;
import android.net.TetheringRequestParcel;
import android.net.dhcp.DhcpServerCallbacks;
import android.net.dhcp.DhcpServingParamsParcel;
@@ -364,8 +365,7 @@
IBinder connector;
try {
final long before = System.currentTimeMillis();
- while ((connector = (IBinder) mContext.getSystemService(
- Context.NETWORK_STACK_SERVICE)) == null) {
+ while ((connector = NetworkStack.getService()) == null) {
if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
Log.wtf(TAG, "Timeout, fail to get INetworkStackConnector");
return null;
diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 948266d..3106e0e 100644
--- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -21,7 +21,7 @@
import static android.net.TetheringManager.TETHERING_USB;
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
-import static android.net.TetheringManager.TETHER_ERROR_ENABLE_NAT_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
@@ -448,7 +448,7 @@
usbTeardownOrder.verify(mNetd, times(2)).interfaceSetCfg(
argThat(cfg -> IFACE_NAME.equals(cfg.ifName)));
usbTeardownOrder.verify(mCallback).updateInterfaceState(
- mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
+ mIpServer, STATE_AVAILABLE, TETHER_ERROR_ENABLE_FORWARDING_ERROR);
usbTeardownOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), mLinkPropertiesCaptor.capture());
assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
diff --git a/packages/Tethering/tests/unit/src/android/net/util/TetheringUtilsTest.java b/packages/Tethering/tests/unit/src/android/net/util/TetheringUtilsTest.java
new file mode 100644
index 0000000..1499f3b
--- /dev/null
+++ b/packages/Tethering/tests/unit/src/android/net/util/TetheringUtilsTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.net.util;
+
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.net.LinkAddress;
+import android.net.TetheringRequestParcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.MiscAssertsKt;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class TetheringUtilsTest {
+ private static final LinkAddress TEST_SERVER_ADDR = new LinkAddress("192.168.43.1/24");
+ private static final LinkAddress TEST_CLIENT_ADDR = new LinkAddress("192.168.43.5/24");
+ private TetheringRequestParcel mTetheringRequest;
+
+ @Before
+ public void setUp() {
+ mTetheringRequest = makeTetheringRequestParcel();
+ }
+
+ public TetheringRequestParcel makeTetheringRequestParcel() {
+ final TetheringRequestParcel request = new TetheringRequestParcel();
+ request.tetheringType = TETHERING_WIFI;
+ request.localIPv4Address = TEST_SERVER_ADDR;
+ request.staticClientAddress = TEST_CLIENT_ADDR;
+ request.exemptFromEntitlementCheck = false;
+ request.showProvisioningUi = true;
+ return request;
+ }
+
+ @Test
+ public void testIsTetheringRequestEquals() throws Exception {
+ TetheringRequestParcel request = makeTetheringRequestParcel();
+
+ assertTrue(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, mTetheringRequest));
+ assertTrue(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request));
+ assertTrue(TetheringUtils.isTetheringRequestEquals(null, null));
+ assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, null));
+ assertFalse(TetheringUtils.isTetheringRequestEquals(null, mTetheringRequest));
+
+ request = makeTetheringRequestParcel();
+ request.tetheringType = TETHERING_USB;
+ assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request));
+
+ request = makeTetheringRequestParcel();
+ request.localIPv4Address = null;
+ request.staticClientAddress = null;
+ assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request));
+
+ request = makeTetheringRequestParcel();
+ request.exemptFromEntitlementCheck = true;
+ assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request));
+
+ request = makeTetheringRequestParcel();
+ request.showProvisioningUi = false;
+ assertFalse(TetheringUtils.isTetheringRequestEquals(mTetheringRequest, request));
+
+ MiscAssertsKt.assertFieldCountEquals(5, TetheringRequestParcel.class);
+ }
+}
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
index 3a1d4a6..0a7850b 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
@@ -21,7 +21,7 @@
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
-import static android.net.TetheringManager.TETHER_ERROR_PROVISION_FAILED;
+import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -284,11 +284,11 @@
assertEquals(0, mEnMgr.uiProvisionCount);
mEnMgr.reset();
// 3. No cache value and ui entitlement check is needed.
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- assertEquals(TETHER_ERROR_PROVISION_FAILED, resultCode);
+ assertEquals(TETHER_ERROR_PROVISIONING_FAILED, resultCode);
mCallbacklatch.countDown();
}
};
@@ -297,12 +297,13 @@
callbackTimeoutHelper(mCallbacklatch);
assertEquals(1, mEnMgr.uiProvisionCount);
mEnMgr.reset();
- // 4. Cache value is TETHER_ERROR_PROVISION_FAILED and don't need to run entitlement check.
+ // 4. Cache value is TETHER_ERROR_PROVISIONING_FAILED and don't need to run entitlement
+ // check.
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
receiver = new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- assertEquals(TETHER_ERROR_PROVISION_FAILED, resultCode);
+ assertEquals(TETHER_ERROR_PROVISIONING_FAILED, resultCode);
mCallbacklatch.countDown();
}
};
@@ -311,7 +312,7 @@
callbackTimeoutHelper(mCallbacklatch);
assertEquals(0, mEnMgr.uiProvisionCount);
mEnMgr.reset();
- // 5. Cache value is TETHER_ERROR_PROVISION_FAILED and ui entitlement check is needed.
+ // 5. Cache value is TETHER_ERROR_PROVISIONING_FAILED and ui entitlement check is needed.
mEnMgr.fakeEntitlementResult = TETHER_ERROR_NO_ERROR;
receiver = new ResultReceiver(null) {
@Override
@@ -364,7 +365,7 @@
public void verifyPermissionResult() {
setupForRequiredProvisioning();
mEnMgr.notifyUpstream(true);
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll();
assertFalse(mEnMgr.isCellularUpstreamPermitted());
@@ -380,15 +381,15 @@
public void verifyPermissionIfAllNotApproved() {
setupForRequiredProvisioning();
mEnMgr.notifyUpstream(true);
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
mLooper.dispatchAll();
assertFalse(mEnMgr.isCellularUpstreamPermitted());
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true);
mLooper.dispatchAll();
assertFalse(mEnMgr.isCellularUpstreamPermitted());
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_BLUETOOTH, true);
mLooper.dispatchAll();
assertFalse(mEnMgr.isCellularUpstreamPermitted());
@@ -403,7 +404,7 @@
mLooper.dispatchAll();
assertTrue(mEnMgr.isCellularUpstreamPermitted());
mLooper.dispatchAll();
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
mEnMgr.startProvisioningIfNeeded(TETHERING_USB, true);
mLooper.dispatchAll();
assertTrue(mEnMgr.isCellularUpstreamPermitted());
@@ -465,7 +466,7 @@
assertEquals(0, mEnMgr.silentProvisionCount);
mEnMgr.reset();
// 6. switch upstream back to mobile again
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
mEnMgr.notifyUpstream(true);
mLooper.dispatchAll();
assertEquals(0, mEnMgr.uiProvisionCount);
@@ -477,7 +478,7 @@
public void testCallStopTetheringWhenUiProvisioningFail() {
setupForRequiredProvisioning();
verify(mEntitlementFailedListener, times(0)).onUiEntitlementFailed(TETHERING_WIFI);
- mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISION_FAILED;
+ mEnMgr.fakeEntitlementResult = TETHER_ERROR_PROVISIONING_FAILED;
mEnMgr.notifyUpstream(true);
mLooper.dispatchAll();
mEnMgr.startProvisioningIfNeeded(TETHERING_WIFI, true);
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
index 7e62e5a..fe84086 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -33,6 +33,8 @@
import static com.android.testutils.MiscAssertsKt.assertThrows;
import static com.android.testutils.NetworkStatsUtilsKt.orderInsensitiveEquals;
+import static junit.framework.Assert.assertNotNull;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -61,8 +63,7 @@
import android.net.NetworkStats;
import android.net.NetworkStats.Entry;
import android.net.RouteInfo;
-import android.net.netstats.provider.AbstractNetworkStatsProvider;
-import android.net.netstats.provider.NetworkStatsProviderCallback;
+import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.net.util.SharedLog;
import android.os.Handler;
import android.os.Looper;
@@ -108,12 +109,10 @@
@Mock private ApplicationInfo mApplicationInfo;
@Mock private Context mContext;
@Mock private NetworkStatsManager mStatsManager;
- @Mock private NetworkStatsProviderCallback mTetherStatsProviderCb;
+ @Mock private INetworkStatsProviderCallback mTetherStatsProviderCb;
+ private OffloadController.OffloadTetheringStatsProvider mTetherStatsProvider;
private final ArgumentCaptor<ArrayList> mStringArrayCaptor =
ArgumentCaptor.forClass(ArrayList.class);
- private final ArgumentCaptor<OffloadController.OffloadTetheringStatsProvider>
- mTetherStatsProviderCaptor =
- ArgumentCaptor.forClass(OffloadController.OffloadTetheringStatsProvider.class);
private final ArgumentCaptor<OffloadHardwareInterface.ControlCallback> mControlCallbackCaptor =
ArgumentCaptor.forClass(OffloadHardwareInterface.ControlCallback.class);
private MockContentResolver mContentResolver;
@@ -126,8 +125,6 @@
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
when(mContext.getContentResolver()).thenReturn(mContentResolver);
FakeSettingsProvider.clearSettingsProvider();
- when(mStatsManager.registerNetworkStatsProvider(anyString(), any()))
- .thenReturn(mTetherStatsProviderCb);
}
@After public void tearDown() throws Exception {
@@ -154,8 +151,14 @@
private OffloadController makeOffloadController() throws Exception {
OffloadController offload = new OffloadController(new Handler(Looper.getMainLooper()),
mHardware, mContentResolver, mStatsManager, new SharedLog("test"));
+ final ArgumentCaptor<OffloadController.OffloadTetheringStatsProvider>
+ tetherStatsProviderCaptor =
+ ArgumentCaptor.forClass(OffloadController.OffloadTetheringStatsProvider.class);
verify(mStatsManager).registerNetworkStatsProvider(anyString(),
- mTetherStatsProviderCaptor.capture());
+ tetherStatsProviderCaptor.capture());
+ mTetherStatsProvider = tetherStatsProviderCaptor.getValue();
+ assertNotNull(mTetherStatsProvider);
+ mTetherStatsProvider.setProviderCallbackBinder(mTetherStatsProviderCb);
return offload;
}
@@ -413,9 +416,6 @@
final OffloadController offload = makeOffloadController();
offload.start();
- final OffloadController.OffloadTetheringStatsProvider provider =
- mTetherStatsProviderCaptor.getValue();
-
final String ethernetIface = "eth1";
final String mobileIface = "rmnet_data0";
@@ -443,15 +443,15 @@
inOrder.verify(mHardware, times(1)).getForwardedStats(eq(mobileIface));
// Verify that the fetched stats are stored.
- final NetworkStats ifaceStats = provider.getTetherStats(STATS_PER_IFACE);
- final NetworkStats uidStats = provider.getTetherStats(STATS_PER_UID);
+ final NetworkStats ifaceStats = mTetherStatsProvider.getTetherStats(STATS_PER_IFACE);
+ final NetworkStats uidStats = mTetherStatsProvider.getTetherStats(STATS_PER_UID);
final NetworkStats expectedIfaceStats = new NetworkStats(0L, 2)
- .addValues(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999))
- .addValues(buildTestEntry(STATS_PER_IFACE, ethernetIface, 12345, 54321));
+ .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999))
+ .addEntry(buildTestEntry(STATS_PER_IFACE, ethernetIface, 12345, 54321));
final NetworkStats expectedUidStats = new NetworkStats(0L, 2)
- .addValues(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999))
- .addValues(buildTestEntry(STATS_PER_UID, ethernetIface, 12345, 54321));
+ .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999))
+ .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 12345, 54321));
assertTrue(orderInsensitiveEquals(expectedIfaceStats, ifaceStats));
assertTrue(orderInsensitiveEquals(expectedUidStats, uidStats));
@@ -462,13 +462,12 @@
NetworkStats.class);
// Force pushing stats update to verify the stats reported.
- provider.pushTetherStats();
- verify(mTetherStatsProviderCb, times(1)).onStatsUpdated(anyInt(),
- ifaceStatsCaptor.capture(), uidStatsCaptor.capture());
+ mTetherStatsProvider.pushTetherStats();
+ verify(mTetherStatsProviderCb, times(1))
+ .notifyStatsUpdated(anyInt(), ifaceStatsCaptor.capture(), uidStatsCaptor.capture());
assertTrue(orderInsensitiveEquals(expectedIfaceStats, ifaceStatsCaptor.getValue()));
assertTrue(orderInsensitiveEquals(expectedUidStats, uidStatsCaptor.getValue()));
-
when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn(
new ForwardedStats(100000, 100000));
offload.setUpstreamLinkProperties(null);
@@ -483,31 +482,31 @@
inOrder.verifyNoMoreInteractions();
// Verify that the stored stats is accumulated.
- final NetworkStats ifaceStatsAccu = provider.getTetherStats(STATS_PER_IFACE);
- final NetworkStats uidStatsAccu = provider.getTetherStats(STATS_PER_UID);
+ final NetworkStats ifaceStatsAccu = mTetherStatsProvider.getTetherStats(STATS_PER_IFACE);
+ final NetworkStats uidStatsAccu = mTetherStatsProvider.getTetherStats(STATS_PER_UID);
final NetworkStats expectedIfaceStatsAccu = new NetworkStats(0L, 2)
- .addValues(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999))
- .addValues(buildTestEntry(STATS_PER_IFACE, ethernetIface, 112345, 154321));
+ .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 999, 99999))
+ .addEntry(buildTestEntry(STATS_PER_IFACE, ethernetIface, 112345, 154321));
final NetworkStats expectedUidStatsAccu = new NetworkStats(0L, 2)
- .addValues(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999))
- .addValues(buildTestEntry(STATS_PER_UID, ethernetIface, 112345, 154321));
+ .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 999, 99999))
+ .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 112345, 154321));
assertTrue(orderInsensitiveEquals(expectedIfaceStatsAccu, ifaceStatsAccu));
assertTrue(orderInsensitiveEquals(expectedUidStatsAccu, uidStatsAccu));
// Verify that only diff of stats is reported.
reset(mTetherStatsProviderCb);
- provider.pushTetherStats();
+ mTetherStatsProvider.pushTetherStats();
final NetworkStats expectedIfaceStatsDiff = new NetworkStats(0L, 2)
- .addValues(buildTestEntry(STATS_PER_IFACE, mobileIface, 0, 0))
- .addValues(buildTestEntry(STATS_PER_IFACE, ethernetIface, 100000, 100000));
+ .addEntry(buildTestEntry(STATS_PER_IFACE, mobileIface, 0, 0))
+ .addEntry(buildTestEntry(STATS_PER_IFACE, ethernetIface, 100000, 100000));
final NetworkStats expectedUidStatsDiff = new NetworkStats(0L, 2)
- .addValues(buildTestEntry(STATS_PER_UID, mobileIface, 0, 0))
- .addValues(buildTestEntry(STATS_PER_UID, ethernetIface, 100000, 100000));
- verify(mTetherStatsProviderCb, times(1)).onStatsUpdated(anyInt(),
- ifaceStatsCaptor.capture(), uidStatsCaptor.capture());
+ .addEntry(buildTestEntry(STATS_PER_UID, mobileIface, 0, 0))
+ .addEntry(buildTestEntry(STATS_PER_UID, ethernetIface, 100000, 100000));
+ verify(mTetherStatsProviderCb, times(1))
+ .notifyStatsUpdated(anyInt(), ifaceStatsCaptor.capture(), uidStatsCaptor.capture());
assertTrue(orderInsensitiveEquals(expectedIfaceStatsDiff, ifaceStatsCaptor.getValue()));
assertTrue(orderInsensitiveEquals(expectedUidStatsDiff, uidStatsCaptor.getValue()));
}
@@ -529,19 +528,18 @@
lp.setInterfaceName(ethernetIface);
offload.setUpstreamLinkProperties(lp);
- AbstractNetworkStatsProvider provider = mTetherStatsProviderCaptor.getValue();
final InOrder inOrder = inOrder(mHardware);
when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(true);
when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true);
// Applying an interface quota to the current upstream immediately sends it to the hardware.
- provider.setLimit(ethernetIface, ethernetLimit);
+ mTetherStatsProvider.onSetLimit(ethernetIface, ethernetLimit);
waitForIdle();
inOrder.verify(mHardware).setDataLimit(ethernetIface, ethernetLimit);
inOrder.verifyNoMoreInteractions();
// Applying an interface quota to another upstream does not take any immediate action.
- provider.setLimit(mobileIface, mobileLimit);
+ mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit);
waitForIdle();
inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong());
@@ -554,7 +552,7 @@
// Setting a limit of ITetheringStatsProvider.QUOTA_UNLIMITED causes the limit to be set
// to Long.MAX_VALUE.
- provider.setLimit(mobileIface, ITetheringStatsProvider.QUOTA_UNLIMITED);
+ mTetherStatsProvider.onSetLimit(mobileIface, ITetheringStatsProvider.QUOTA_UNLIMITED);
waitForIdle();
inOrder.verify(mHardware).setDataLimit(mobileIface, Long.MAX_VALUE);
@@ -562,7 +560,7 @@
when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(false);
lp.setInterfaceName(ethernetIface);
offload.setUpstreamLinkProperties(lp);
- provider.setLimit(mobileIface, mobileLimit);
+ mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit);
waitForIdle();
inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong());
@@ -571,7 +569,7 @@
when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(false);
lp.setInterfaceName(mobileIface);
offload.setUpstreamLinkProperties(lp);
- provider.setLimit(mobileIface, mobileLimit);
+ mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit);
waitForIdle();
inOrder.verify(mHardware).getForwardedStats(ethernetIface);
inOrder.verify(mHardware).stopOffloadControl();
@@ -587,7 +585,7 @@
OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
callback.onStoppedLimitReached();
- verify(mTetherStatsProviderCb, times(1)).onStatsUpdated(anyInt(), any(), any());
+ verify(mTetherStatsProviderCb, times(1)).notifyStatsUpdated(anyInt(), any(), any());
}
@Test
@@ -691,7 +689,7 @@
verify(mHardware, times(1)).getForwardedStats(eq(RMNET0));
verify(mHardware, times(1)).getForwardedStats(eq(WLAN0));
// TODO: verify the exact stats reported.
- verify(mTetherStatsProviderCb, times(1)).onStatsUpdated(anyInt(), any(), any());
+ verify(mTetherStatsProviderCb, times(1)).notifyStatsUpdated(anyInt(), any(), any());
verifyNoMoreInteractions(mTetherStatsProviderCb);
verifyNoMoreInteractions(mHardware);
}
@@ -756,7 +754,7 @@
// Verify forwarded stats behaviour.
verify(mHardware, times(1)).getForwardedStats(eq(RMNET0));
verify(mHardware, times(1)).getForwardedStats(eq(WLAN0));
- verify(mTetherStatsProviderCb, times(1)).onStatsUpdated(anyInt(), any(), any());
+ verify(mTetherStatsProviderCb, times(1)).notifyStatsUpdated(anyInt(), any(), any());
verifyNoMoreInteractions(mTetherStatsProviderCb);
// TODO: verify local prefixes and downstreams are also pushed to the HAL.
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 820c852..60d7ad1 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
@@ -82,6 +82,7 @@
import android.net.ConnectivityManager;
import android.net.EthernetManager;
import android.net.EthernetManager.TetheredInterfaceRequest;
+import android.net.IIntResultListener;
import android.net.INetd;
import android.net.ITetheringEventCallback;
import android.net.InetAddresses;
@@ -499,10 +500,16 @@
return new Tethering(mTetheringDependencies);
}
- private TetheringRequestParcel createTetheringRquestParcel(final int type) {
+ private TetheringRequestParcel createTetheringRequestParcel(final int type) {
+ return createTetheringRequestParcel(type, null, null);
+ }
+
+ private TetheringRequestParcel createTetheringRequestParcel(final int type,
+ final LinkAddress serverAddr, final LinkAddress clientAddr) {
final TetheringRequestParcel request = new TetheringRequestParcel();
request.tetheringType = type;
- request.localIPv4Address = null;
+ request.localIPv4Address = serverAddr;
+ request.staticClientAddress = clientAddr;
request.exemptFromEntitlementCheck = false;
request.showProvisioningUi = false;
@@ -616,7 +623,7 @@
private void prepareNcmTethering() {
// Emulate startTethering(TETHERING_NCM) called
- mTethering.startTethering(createTetheringRquestParcel(TETHERING_NCM), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_NCM), null);
mLooper.dispatchAll();
verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NCM);
@@ -629,7 +636,7 @@
.thenReturn(upstreamState);
// Emulate pressing the USB tethering button in Settings UI.
- mTethering.startTethering(createTetheringRquestParcel(TETHERING_USB), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB), null);
mLooper.dispatchAll();
verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
@@ -903,7 +910,7 @@
when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
// Emulate pressing the WiFi tethering button.
- mTethering.startTethering(createTetheringRquestParcel(TETHERING_WIFI), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager);
@@ -931,7 +938,7 @@
when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
// Emulate pressing the WiFi tethering button.
- mTethering.startTethering(createTetheringRquestParcel(TETHERING_WIFI), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager);
@@ -1008,7 +1015,7 @@
doThrow(new RemoteException()).when(mNetd).ipfwdEnableForwarding(TETHERING_NAME);
// Emulate pressing the WiFi tethering button.
- mTethering.startTethering(createTetheringRquestParcel(TETHERING_WIFI), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager);
@@ -1303,7 +1310,7 @@
tetherState = callback.pollTetherStatesChanged();
assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME});
- mTethering.startTethering(createTetheringRquestParcel(TETHERING_WIFI), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null);
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
mLooper.dispatchAll();
tetherState = callback.pollTetherStatesChanged();
@@ -1398,10 +1405,10 @@
public void testNoDuplicatedEthernetRequest() throws Exception {
final TetheredInterfaceRequest mockRequest = mock(TetheredInterfaceRequest.class);
when(mEm.requestTetheredInterface(any(), any())).thenReturn(mockRequest);
- mTethering.startTethering(createTetheringRquestParcel(TETHERING_ETHERNET), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET), null);
mLooper.dispatchAll();
verify(mEm, times(1)).requestTetheredInterface(any(), any());
- mTethering.startTethering(createTetheringRquestParcel(TETHERING_ETHERNET), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET), null);
mLooper.dispatchAll();
verifyNoMoreInteractions(mEm);
mTethering.stopTethering(TETHERING_ETHERNET);
@@ -1580,6 +1587,86 @@
assertTrue(element + " not found in " + collection, collection.contains(element));
}
+ private class ResultListener extends IIntResultListener.Stub {
+ private final int mExpectedResult;
+ private boolean mHasResult = false;
+ ResultListener(final int expectedResult) {
+ mExpectedResult = expectedResult;
+ }
+
+ @Override
+ public void onResult(final int resultCode) {
+ mHasResult = true;
+ if (resultCode != mExpectedResult) {
+ fail("expected result: " + mExpectedResult + " but actual result: " + resultCode);
+ }
+ }
+
+ public void assertHasResult() {
+ if (!mHasResult) fail("No callback result");
+ }
+ }
+
+ @Test
+ public void testMultipleStartTethering() throws Exception {
+ final LinkAddress serverLinkAddr = new LinkAddress("192.168.20.1/24");
+ final LinkAddress clientLinkAddr = new LinkAddress("192.168.20.42/24");
+ final String serverAddr = "192.168.20.1";
+ final ResultListener firstResult = new ResultListener(TETHER_ERROR_NO_ERROR);
+ final ResultListener secondResult = new ResultListener(TETHER_ERROR_NO_ERROR);
+ final ResultListener thirdResult = new ResultListener(TETHER_ERROR_NO_ERROR);
+
+ // Enable USB tethering and check that Tethering starts USB.
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB,
+ null, null), firstResult);
+ mLooper.dispatchAll();
+ firstResult.assertHasResult();
+ verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
+ verifyNoMoreInteractions(mUsbManager);
+
+ // Enable USB tethering again with the same request and expect no change to USB.
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB,
+ null, null), secondResult);
+ mLooper.dispatchAll();
+ secondResult.assertHasResult();
+ verify(mUsbManager, never()).setCurrentFunctions(UsbManager.FUNCTION_NONE);
+ reset(mUsbManager);
+
+ // Enable USB tethering with a different request and expect that USB is stopped and
+ // started.
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB,
+ serverLinkAddr, clientLinkAddr), thirdResult);
+ mLooper.dispatchAll();
+ thirdResult.assertHasResult();
+ verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
+ verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
+
+ // Expect that when USB comes up, the DHCP server is configured with the requested address.
+ mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
+ sendUsbBroadcast(true, true, true, TETHERING_USB);
+ mLooper.dispatchAll();
+ verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
+ any(), any());
+ verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr)));
+ }
+
+ @Test
+ public void testRequestStaticServerIp() throws Exception {
+ final LinkAddress serverLinkAddr = new LinkAddress("192.168.20.1/24");
+ final LinkAddress clientLinkAddr = new LinkAddress("192.168.20.42/24");
+ final String serverAddr = "192.168.20.1";
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB,
+ serverLinkAddr, clientLinkAddr), null);
+ mLooper.dispatchAll();
+ verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
+ mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
+ sendUsbBroadcast(true, true, true, TETHERING_USB);
+ mLooper.dispatchAll();
+ verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr)));
+
+ // TODO: test static client address.
+ }
+
// TODO: Test that a request for hotspot mode doesn't interfere with an
// already operating tethering mode interface.
}
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 8a4a1c6..93bffe9 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -164,6 +164,9 @@
}
if (DEBUG) Slog.v(TAG, "Storing wallpaper metadata");
backupFile(infoStage, data);
+ } else {
+ Slog.w(TAG, "Wallpaper metadata file doesn't exist: " +
+ mWallpaperFile.getPath());
}
if (sysEligible && mWallpaperFile.exists()) {
if (sysChanged || !imageStage.exists()) {
@@ -173,6 +176,10 @@
if (DEBUG) Slog.v(TAG, "Storing system wallpaper image");
backupFile(imageStage, data);
prefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply();
+ } else {
+ Slog.w(TAG, "Not backing up wallpaper as one of conditions is not "
+ + "met: sysEligible = " + sysEligible + " wallpaperFileExists = "
+ + mWallpaperFile.exists());
}
// If there's no lock wallpaper, then we have nothing to add to the backup.
@@ -181,7 +188,7 @@
if (DEBUG) Slog.v(TAG, "Removed lock wallpaper; deleting");
lockImageStage.delete();
}
- if (DEBUG) Slog.v(TAG, "No lock paper set, add nothing to backup");
+ Slog.d(TAG, "No lockscreen wallpaper set, add nothing to backup");
prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
return;
}
@@ -195,6 +202,12 @@
if (DEBUG) Slog.v(TAG, "Storing lock wallpaper image");
backupFile(lockImageStage, data);
prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply();
+ } else {
+ Slog.w(TAG, "Not backing up lockscreen wallpaper as one of conditions is not "
+ + "met: lockEligible = " + lockEligible + " hasLockWallpaper = "
+ + hasLockWallpaper + " lockWallpaperFileExists = "
+ + mLockWallpaperFile.exists() + " quotaExceeded (last time) = "
+ + mQuotaExceeded);
}
} catch (Exception e) {
Slog.e(TAG, "Unable to back up wallpaper", e);
@@ -216,9 +229,7 @@
@Override
public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
- if (DEBUG) {
- Slog.i(TAG, "Quota exceeded (" + backupDataBytes + " vs " + quotaBytes + ')');
- }
+ Slog.i(TAG, "Quota exceeded (" + backupDataBytes + " vs " + quotaBytes + ')');
try (FileOutputStream f = new FileOutputStream(mQuotaFile)) {
f.write(0);
} catch (Exception e) {
@@ -230,9 +241,7 @@
// then post-process in onRestoreFinished() to apply the new wallpaper.
@Override
public void onRestoreFinished() {
- if (DEBUG) {
- Slog.v(TAG, "onRestoreFinished()");
- }
+ Slog.v(TAG, "onRestoreFinished()");
final File filesDir = getFilesDir();
final File infoStage = new File(filesDir, INFO_STAGE);
final File imageStage = new File (filesDir, IMAGE_STAGE);
@@ -253,9 +262,7 @@
// And reset to the wallpaper service we should be using
ComponentName wpService = parseWallpaperComponent(infoStage, "wp");
if (servicePackageExists(wpService)) {
- if (DEBUG) {
- Slog.i(TAG, "Using wallpaper service " + wpService);
- }
+ Slog.i(TAG, "Using wallpaper service " + wpService);
mWm.setWallpaperComponent(wpService, UserHandle.USER_SYSTEM);
if (!lockImageStage.exists()) {
// We have a live wallpaper and no static lock image,
@@ -273,9 +280,7 @@
} catch (Exception e) {
Slog.e(TAG, "Unable to restore wallpaper: " + e.getMessage());
} finally {
- if (DEBUG) {
- Slog.v(TAG, "Restore finished; clearing backup bookkeeping");
- }
+ Slog.v(TAG, "Restore finished; clearing backup bookkeeping");
infoStage.delete();
imageStage.delete();
lockImageStage.delete();
@@ -295,14 +300,14 @@
// relies on a priori knowledge of the wallpaper info file schema.
Rect cropHint = parseCropHint(info, hintTag);
if (cropHint != null) {
- Slog.i(TAG, "Got restored wallpaper; applying which=" + which);
- if (DEBUG) {
- Slog.v(TAG, "Restored crop hint " + cropHint);
- }
+ Slog.i(TAG, "Got restored wallpaper; applying which=" + which
+ + "; cropHint = " + cropHint);
try (FileInputStream in = new FileInputStream(stage)) {
mWm.setStream(in, cropHint.isEmpty() ? null : cropHint, true, which);
} finally {} // auto-closes 'in'
}
+ } else {
+ Slog.d(TAG, "Restore data doesn't exist for file " + stage.getPath());
}
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index ad21075..260703d 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -3647,10 +3647,12 @@
}
private void updateAppOpsLocked(Host host, boolean visible) {
- // The launcher must be at TOP.
- final int procState = mActivityManagerInternal.getUidProcessState(host.id.uid);
- if (procState > ActivityManager.PROCESS_STATE_TOP) {
- return;
+ if (visible) {
+ final int procState = mActivityManagerInternal.getUidProcessState(host.id.uid);
+ if (procState > ActivityManager.PROCESS_STATE_TOP) {
+ // The launcher must be at TOP.
+ return;
+ }
}
final List<ResolveInfo> allHomeCandidates = new ArrayList<>();
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index 53afa6e..b4b0641 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -37,7 +37,6 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.service.autofill.Dataset;
-import android.service.autofill.InlineAction;
import android.service.autofill.augmented.AugmentedAutofillService;
import android.service.autofill.augmented.IAugmentedAutofillService;
import android.service.autofill.augmented.IFillCallback;
@@ -167,12 +166,12 @@
focusedId, focusedValue, requestTime, inlineSuggestionsRequest,
new IFillCallback.Stub() {
@Override
- public void onSuccess(@Nullable List<Dataset> inlineSuggestionsData,
- @Nullable List<InlineAction> inlineActions) {
+ public void onSuccess(
+ @Nullable List<Dataset> inlineSuggestionsData) {
mCallbacks.resetLastResponse();
maybeRequestShowInlineSuggestions(sessionId,
inlineSuggestionsRequest, inlineSuggestionsData,
- inlineActions, focusedId, inlineSuggestionsCallback,
+ focusedId, inlineSuggestionsCallback,
client, onErrorCallback, remoteRenderService);
requestAutofill.complete(null);
}
@@ -237,8 +236,7 @@
private void maybeRequestShowInlineSuggestions(int sessionId,
@Nullable InlineSuggestionsRequest request,
- @Nullable List<Dataset> inlineSuggestionsData,
- @Nullable List<InlineAction> inlineActions, @NonNull AutofillId focusedId,
+ @Nullable List<Dataset> inlineSuggestionsData, @NonNull AutofillId focusedId,
@Nullable Function<InlineSuggestionsResponse, Boolean> inlineSuggestionsCallback,
@NonNull IAutoFillManagerClient client, @NonNull Runnable onErrorCallback,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
@@ -251,7 +249,7 @@
final InlineSuggestionsResponse inlineSuggestionsResponse =
InlineSuggestionFactory.createAugmentedInlineSuggestionsResponse(
- request, inlineSuggestionsData, inlineActions, focusedId,
+ request, inlineSuggestionsData, focusedId,
dataset -> {
mCallbacks.logAugmentedAutofillSelected(sessionId,
dataset.getId());
@@ -260,8 +258,13 @@
final int size = fieldIds.size();
final boolean hideHighlight = size == 1
&& fieldIds.get(0).equals(focusedId);
- client.autofill(sessionId, fieldIds, dataset.getFieldValues(),
- hideHighlight);
+ if (dataset.getAuthentication() != null) {
+ client.startIntentSender(dataset.getAuthentication(),
+ new Intent());
+ } else {
+ client.autofill(sessionId, fieldIds, dataset.getFieldValues(),
+ hideHighlight);
+ }
} catch (RemoteException e) {
Slog.w(TAG, "Encounter exception autofilling the values");
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index de31118..8032e9b 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -311,6 +311,10 @@
*/
private final AssistDataReceiverImpl mAssistReceiver = new AssistDataReceiverImpl();
+ /**
+ * TODO(b/151867668): improve how asynchronous data dependencies are handled, without using
+ * CountDownLatch.
+ */
private final class AssistDataReceiverImpl extends IAssistDataReceiver.Stub {
@GuardedBy("mLock")
@@ -318,7 +322,7 @@
@GuardedBy("mLock")
private FillRequest mPendingFillRequest;
@GuardedBy("mLock")
- private CountDownLatch mCountDownLatch;
+ private CountDownLatch mCountDownLatch = new CountDownLatch(0);
@Nullable Consumer<InlineSuggestionsRequest> newAutofillRequestLocked(
boolean isInlineRequest) {
@@ -327,6 +331,9 @@
mPendingInlineSuggestionsRequest = null;
return isInlineRequest ? (inlineSuggestionsRequest) -> {
synchronized (mLock) {
+ if (mCountDownLatch.getCount() == 0) {
+ return;
+ }
mPendingInlineSuggestionsRequest = inlineSuggestionsRequest;
mCountDownLatch.countDown();
maybeRequestFillLocked();
@@ -335,8 +342,7 @@
}
void maybeRequestFillLocked() {
- if (mCountDownLatch == null || mCountDownLatch.getCount() > 0
- || mPendingFillRequest == null) {
+ if (mCountDownLatch.getCount() > 0 || mPendingFillRequest == null) {
return;
}
if (mPendingInlineSuggestionsRequest != null) {
@@ -347,7 +353,6 @@
mRemoteFillService.onFillRequest(mPendingFillRequest);
mPendingInlineSuggestionsRequest = null;
mPendingFillRequest = null;
- mCountDownLatch = null;
}
@Override
@@ -447,9 +452,15 @@
request = new FillRequest(requestId, contexts, mClientState, flags,
/*inlineSuggestionsRequest=*/null);
- mPendingFillRequest = request;
- mCountDownLatch.countDown();
- maybeRequestFillLocked();
+ if (mCountDownLatch.getCount() > 0) {
+ mPendingFillRequest = request;
+ mCountDownLatch.countDown();
+ maybeRequestFillLocked();
+ } else {
+ // TODO(b/151867668): ideally this case should not happen, but it was
+ // observed, we should figure out why and fix.
+ mRemoteFillService.onFillRequest(request);
+ }
}
if (mActivityToken != null) {
@@ -2726,8 +2737,7 @@
InlineSuggestionsResponse inlineSuggestionsResponse =
InlineSuggestionFactory.createInlineSuggestionsResponse(
- inlineSuggestionsRequest.get(),
- response, filterText, response.getInlineActions(), mCurrentViewId,
+ inlineSuggestionsRequest.get(), response, filterText, mCurrentViewId,
this, () -> {
synchronized (mLock) {
mInlineSuggestionSession.hideInlineSuggestionsUi(mCurrentViewId);
diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
index 0ca9dd9..71d4ace 100644
--- a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
@@ -21,13 +21,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.IntentSender;
import android.os.IBinder;
import android.os.RemoteException;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
import android.service.autofill.IInlineSuggestionUiCallback;
-import android.service.autofill.InlineAction;
import android.service.autofill.InlinePresentation;
import android.text.TextUtils;
import android.util.Slog;
@@ -73,8 +71,7 @@
@Nullable
public static InlineSuggestionsResponse createInlineSuggestionsResponse(
@NonNull InlineSuggestionsRequest request, @NonNull FillResponse response,
- @Nullable String filterText, @Nullable List<InlineAction> inlineActions,
- @NonNull AutofillId autofillId,
+ @Nullable String filterText, @NonNull AutofillId autofillId,
@NonNull AutoFillUI.AutoFillUiCallback client, @NonNull Runnable onErrorCallback,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
if (sDebug) Slog.d(TAG, "createInlineSuggestionsResponse called");
@@ -96,7 +93,7 @@
final InlinePresentation inlineAuthentication =
response.getAuthentication() == null ? null : response.getInlinePresentation();
return createInlineSuggestionsResponseInternal(/* isAugmented= */ false, request,
- response.getDatasets(), filterText, inlineAuthentication, inlineActions, autofillId,
+ response.getDatasets(), filterText, inlineAuthentication, autofillId,
onErrorCallback, onClickFactory, remoteRenderService);
}
@@ -107,15 +104,14 @@
@Nullable
public static InlineSuggestionsResponse createAugmentedInlineSuggestionsResponse(
@NonNull InlineSuggestionsRequest request, @NonNull List<Dataset> datasets,
- @Nullable List<InlineAction> inlineActions, @NonNull AutofillId autofillId,
+ @NonNull AutofillId autofillId,
@NonNull InlineSuggestionUiCallback inlineSuggestionUiCallback,
@NonNull Runnable onErrorCallback,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
if (sDebug) Slog.d(TAG, "createAugmentedInlineSuggestionsResponse called");
return createInlineSuggestionsResponseInternal(/* isAugmented= */ true, request,
datasets, /* filterText= */ null, /* inlineAuthentication= */ null,
- inlineActions, autofillId, onErrorCallback,
- (dataset, datasetIndex) ->
+ autofillId, onErrorCallback, (dataset, datasetIndex) ->
inlineSuggestionUiCallback.autofill(dataset), remoteRenderService);
}
@@ -123,8 +119,7 @@
private static InlineSuggestionsResponse createInlineSuggestionsResponseInternal(
boolean isAugmented, @NonNull InlineSuggestionsRequest request,
@Nullable List<Dataset> datasets, @Nullable String filterText,
- @Nullable InlinePresentation inlineAuthentication,
- @Nullable List<InlineAction> inlineActions, @NonNull AutofillId autofillId,
+ @Nullable InlinePresentation inlineAuthentication, @NonNull AutofillId autofillId,
@NonNull Runnable onErrorCallback, @NonNull BiConsumer<Dataset, Integer> onClickFactory,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService) {
@@ -167,16 +162,6 @@
inlineSuggestions.add(inlineSuggestion);
}
- if (inlineActions != null) {
- for (InlineAction inlineAction : inlineActions) {
- final InlineSuggestion inlineActionSuggestion = createInlineAction(isAugmented,
- mergedInlinePresentation(request, 0, inlineAction.getInlinePresentation()),
- inlineAction.getAction(),
- remoteRenderService, onErrorCallback, request.getHostInputToken(),
- request.getHostDisplayId());
- inlineSuggestions.add(inlineActionSuggestion);
- }
- }
return new InlineSuggestionsResponse(inlineSuggestions);
}
@@ -211,35 +196,6 @@
return valueText.toLowerCase().startsWith(constraintLowerCase);
}
-
- private static InlineSuggestion createInlineAction(boolean isAugmented,
- @NonNull InlinePresentation presentation,
- @NonNull IntentSender action,
- @Nullable RemoteInlineSuggestionRenderService remoteRenderService,
- @NonNull Runnable onErrorCallback, @Nullable IBinder hostInputToken,
- int displayId) {
- final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
- presentation.getInlinePresentationSpec(),
- isAugmented ? InlineSuggestionInfo.SOURCE_PLATFORM
- : InlineSuggestionInfo.SOURCE_AUTOFILL,
- presentation.getAutofillHints(), InlineSuggestionInfo.TYPE_ACTION,
- presentation.isPinned());
- final Runnable onClickAction = () -> {
- try {
- // TODO(b/150499490): route the intent to the client app to have it fired there,
- // so that it will appear as a part of the same task as the client app (similar
- // to the authentication flow).
- action.sendIntent(null, 0, null, null, null);
- } catch (IntentSender.SendIntentException e) {
- onErrorCallback.run();
- Slog.w(TAG, "Error sending inline action intent");
- }
- };
- return new InlineSuggestion(inlineSuggestionInfo,
- createInlineContentProvider(presentation, onClickAction, onErrorCallback,
- remoteRenderService, hostInputToken, displayId));
- }
-
private static InlineSuggestion createInlineSuggestion(boolean isAugmented,
@NonNull Dataset dataset, int datasetIndex,
@NonNull InlinePresentation inlinePresentation,
@@ -247,12 +203,15 @@
@NonNull RemoteInlineSuggestionRenderService remoteRenderService,
@NonNull Runnable onErrorCallback, @Nullable IBinder hostInputToken,
int displayId) {
+ final String suggestionSource = isAugmented ? InlineSuggestionInfo.SOURCE_PLATFORM
+ : InlineSuggestionInfo.SOURCE_AUTOFILL;
+ final String suggestionType =
+ dataset.getAuthentication() == null ? InlineSuggestionInfo.TYPE_SUGGESTION
+ : InlineSuggestionInfo.TYPE_ACTION;
final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
- inlinePresentation.getInlinePresentationSpec(),
- isAugmented ? InlineSuggestionInfo.SOURCE_PLATFORM
- : InlineSuggestionInfo.SOURCE_AUTOFILL,
- inlinePresentation.getAutofillHints(),
- InlineSuggestionInfo.TYPE_SUGGESTION, inlinePresentation.isPinned());
+ inlinePresentation.getInlinePresentationSpec(), suggestionSource,
+ inlinePresentation.getAutofillHints(), suggestionType,
+ inlinePresentation.isPinned());
final InlineSuggestion inlineSuggestion = new InlineSuggestion(inlineSuggestionInfo,
createInlineContentProvider(inlinePresentation,
@@ -270,7 +229,7 @@
final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
inlinePresentation.getInlinePresentationSpec(),
InlineSuggestionInfo.SOURCE_AUTOFILL, inlinePresentation.getAutofillHints(),
- InlineSuggestionInfo.TYPE_SUGGESTION, inlinePresentation.isPinned());
+ InlineSuggestionInfo.TYPE_ACTION, inlinePresentation.isPinned());
return new InlineSuggestion(inlineSuggestionInfo,
createInlineContentProvider(inlinePresentation,
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 6247a63..69154b4 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -157,7 +157,6 @@
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import java.util.Random;
@@ -174,29 +173,47 @@
public static class BackupWakeLock {
private final PowerManager.WakeLock mPowerManagerWakeLock;
private boolean mHasQuit = false;
+ private int mUserId;
- public BackupWakeLock(PowerManager.WakeLock powerManagerWakeLock) {
+ public BackupWakeLock(PowerManager.WakeLock powerManagerWakeLock, int userId) {
mPowerManagerWakeLock = powerManagerWakeLock;
+ mUserId = userId;
}
/** Acquires the {@link PowerManager.WakeLock} if hasn't been quit. */
public synchronized void acquire() {
if (mHasQuit) {
- Slog.v(TAG, "Ignore wakelock acquire after quit: " + mPowerManagerWakeLock.getTag());
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Ignore wakelock acquire after quit: "
+ + mPowerManagerWakeLock.getTag()));
return;
}
mPowerManagerWakeLock.acquire();
- Slog.v(TAG, "Acquired wakelock:" + mPowerManagerWakeLock.getTag());
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Acquired wakelock:" + mPowerManagerWakeLock.getTag()));
}
/** Releases the {@link PowerManager.WakeLock} if hasn't been quit. */
public synchronized void release() {
if (mHasQuit) {
- Slog.v(TAG, "Ignore wakelock release after quit: " + mPowerManagerWakeLock.getTag());
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Ignore wakelock release after quit: "
+ + mPowerManagerWakeLock.getTag()));
return;
}
mPowerManagerWakeLock.release();
- Slog.v(TAG, "Released wakelock:" + mPowerManagerWakeLock.getTag());
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Released wakelock:" + mPowerManagerWakeLock.getTag()));
}
/**
@@ -209,7 +226,10 @@
/** Release the {@link PowerManager.WakeLock} till it isn't held. */
public synchronized void quit() {
while (mPowerManagerWakeLock.isHeld()) {
- Slog.v(TAG, "Releasing wakelock: " + mPowerManagerWakeLock.getTag());
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Releasing wakelock: " + mPowerManagerWakeLock.getTag()));
mPowerManagerWakeLock.release();
}
mHasQuit = true;
@@ -439,7 +459,9 @@
}
if (DEBUG) {
- Slog.v(TAG, "Starting with transport " + currentTransport);
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(userId, "Starting with transport " + currentTransport));
}
TransportManager transportManager =
new TransportManager(userId, context, transportWhitelist, currentTransport);
@@ -451,7 +473,9 @@
new HandlerThread("backup-" + userId, Process.THREAD_PRIORITY_BACKGROUND);
userBackupThread.start();
if (DEBUG) {
- Slog.d(TAG, "Started thread " + userBackupThread.getName() + " for user " + userId);
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(userId, "Started thread " + userBackupThread.getName()));
}
return createAndInitializeService(
@@ -556,7 +580,10 @@
if (userId == UserHandle.USER_SYSTEM) {
mBaseStateDir.mkdirs();
if (!SELinux.restorecon(mBaseStateDir)) {
- Slog.w(TAG, "SELinux restorecon failed on " + mBaseStateDir);
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ userId, "SELinux restorecon failed on " + mBaseStateDir));
}
}
@@ -604,7 +631,8 @@
addPackageParticipantsLocked(null);
}
- mTransportManager = Objects.requireNonNull(transportManager, "transportManager cannot be null");
+ mTransportManager =
+ Objects.requireNonNull(transportManager, "transportManager cannot be null");
mTransportManager.setOnTransportRegisteredListener(this::onTransportRegistered);
mRegisterTransportsRequestedTime = SystemClock.elapsedRealtime();
mBackupHandler.postDelayed(
@@ -620,7 +648,7 @@
mWakelock = new BackupWakeLock(
mPowerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
- "*backup*-" + userId + "-" + userBackupThread.getThreadId()));
+ "*backup*-" + userId + "-" + userBackupThread.getThreadId()), userId);
// Set up the various sorts of package tracking we do
mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule");
@@ -869,7 +897,7 @@
}
private void initPackageTracking() {
- if (MORE_DEBUG) Slog.v(TAG, "` tracking");
+ if (MORE_DEBUG) Slog.v(TAG, addUserIdToLogMessage(mUserId, "` tracking"));
// Remember our ancestral dataset
mTokenFile = new File(mBaseStateDir, "ancestral");
@@ -891,9 +919,9 @@
}
} catch (FileNotFoundException fnf) {
// Probably innocuous
- Slog.v(TAG, "No ancestral data");
+ Slog.v(TAG, addUserIdToLogMessage(mUserId, "No ancestral data"));
} catch (IOException e) {
- Slog.w(TAG, "Unable to read token file", e);
+ Slog.w(TAG, addUserIdToLogMessage(mUserId, "Unable to read token file"), e);
}
mProcessedPackagesJournal = new ProcessedPackagesJournal(mBaseStateDir);
@@ -941,7 +969,10 @@
DataInputStream in = new DataInputStream(bufStream)) {
int version = in.readInt();
if (version != SCHEDULE_FILE_VERSION) {
- Slog.e(TAG, "Unknown backup schedule version " + version);
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Unknown backup schedule version " + version));
return null;
}
@@ -966,14 +997,14 @@
schedule.add(new FullBackupEntry(pkgName, lastBackup));
} else {
if (DEBUG) {
- Slog.i(TAG, "Package " + pkgName
- + " no longer eligible for full backup");
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "Package " + pkgName
+ + " no longer eligible for full backup"));
}
}
} catch (NameNotFoundException e) {
if (DEBUG) {
- Slog.i(TAG, "Package " + pkgName
- + " not installed; dropping from full backup");
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "Package " + pkgName
+ + " not installed; dropping from full backup"));
}
}
}
@@ -986,7 +1017,13 @@
mUserId)) {
if (!foundApps.contains(app.packageName)) {
if (MORE_DEBUG) {
- Slog.i(TAG, "New full backup app " + app.packageName + " found");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "New full backup app "
+ + app.packageName
+ + " found"));
}
schedule.add(new FullBackupEntry(app.packageName, 0));
changed = true;
@@ -996,7 +1033,7 @@
Collections.sort(schedule);
} catch (Exception e) {
- Slog.e(TAG, "Unable to read backup schedule", e);
+ Slog.e(TAG, addUserIdToLogMessage(mUserId, "Unable to read backup schedule"), e);
mFullBackupScheduleFile.delete();
schedule = null;
}
@@ -1052,7 +1089,11 @@
out.write(bufStream.toByteArray());
af.finishWrite(out);
} catch (Exception e) {
- Slog.e(TAG, "Unable to write backup schedule!", e);
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Unable to write backup schedule!"),
+ e);
}
}
}
@@ -1069,12 +1110,17 @@
if (!journal.equals(mJournal)) {
try {
journal.forEach(packageName -> {
- Slog.i(TAG, "Found stale backup journal, scheduling");
- if (MORE_DEBUG) Slog.i(TAG, " " + packageName);
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Found stale backup journal, scheduling"));
+ if (MORE_DEBUG) {
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, " " + packageName));
+ }
dataChangedImpl(packageName);
});
} catch (IOException e) {
- Slog.e(TAG, "Can't read " + journal, e);
+ Slog.e(TAG, addUserIdToLogMessage(mUserId, "Can't read " + journal), e);
}
}
}
@@ -1114,7 +1160,14 @@
boolean isPending, String transportName, String transportDirName) {
synchronized (mQueueLock) {
if (MORE_DEBUG) {
- Slog.i(TAG, "recordInitPending(" + isPending + ") on transport " + transportName);
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "recordInitPending("
+ + isPending
+ + ") on transport "
+ + transportName));
}
File stateDir = new File(mBaseStateDir, transportDirName);
@@ -1175,8 +1228,17 @@
private void onTransportRegistered(String transportName, String transportDirName) {
if (DEBUG) {
long timeMs = SystemClock.elapsedRealtime() - mRegisterTransportsRequestedTime;
- Slog.d(TAG, "Transport " + transportName + " registered " + timeMs
- + "ms after first request (delay = " + INITIALIZATION_DELAY_MILLIS + "ms)");
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Transport "
+ + transportName
+ + " registered "
+ + timeMs
+ + "ms after first request (delay = "
+ + INITIALIZATION_DELAY_MILLIS
+ + "ms)"));
}
File stateDir = new File(mBaseStateDir, transportDirName);
@@ -1202,7 +1264,7 @@
private BroadcastReceiver mPackageTrackingReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if (MORE_DEBUG) {
- Slog.d(TAG, "Received broadcast " + intent);
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Received broadcast " + intent));
}
String action = intent.getAction();
@@ -1222,24 +1284,33 @@
String packageName = uri.getSchemeSpecificPart();
if (packageName != null) {
- packageList = new String[]{packageName};
+ packageList = new String[] {packageName};
}
changed = Intent.ACTION_PACKAGE_CHANGED.equals(action);
if (changed) {
// Look at new transport states for package changed events.
String[] components =
- intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
+ intent.getStringArrayExtra(
+ Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
if (MORE_DEBUG) {
- Slog.i(TAG, "Package " + packageName + " changed");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Package " + packageName + " changed"));
for (int i = 0; i < components.length; i++) {
- Slog.i(TAG, " * " + components[i]);
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, " * " + components[i]));
}
}
mBackupHandler.post(
- () -> mTransportManager.onPackageChanged(packageName, components));
+ () ->
+ mTransportManager.onPackageChanged(
+ packageName, components));
return;
}
@@ -1261,7 +1332,8 @@
if (added) {
synchronized (mBackupParticipants) {
if (replacing) {
- // Remove the entry under the old uid and fall through to re-add. If an app
+ // Remove the entry under the old uid and fall through to re-add. If
+ // an app
// just opted into key/value backup, add it as a known participant.
removePackageParticipantsLocked(packageList, uid);
}
@@ -1275,13 +1347,15 @@
mPackageManager.getPackageInfoAsUser(
packageName, /* flags */ 0, mUserId);
if (AppBackupUtils.appGetsFullBackup(app)
- && AppBackupUtils.appIsEligibleForBackup(app.applicationInfo,
- mUserId)) {
+ && AppBackupUtils.appIsEligibleForBackup(
+ app.applicationInfo, mUserId)) {
enqueueFullBackup(packageName, now);
scheduleNextFullBackupJob(0);
} else {
- // The app might have just transitioned out of full-data into doing
- // key/value backups, or might have just disabled backups entirely. Make
+ // The app might have just transitioned out of full-data into
+ // doing
+ // key/value backups, or might have just disabled backups
+ // entirely. Make
// sure it is no longer in the full-data queue.
synchronized (mQueueLock) {
dequeueFullBackupLocked(packageName);
@@ -1293,17 +1367,23 @@
() -> mTransportManager.onPackageAdded(packageName));
} catch (NameNotFoundException e) {
if (DEBUG) {
- Slog.w(TAG, "Can't resolve new app " + packageName);
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Can't resolve new app " + packageName));
}
}
}
- // Whenever a package is added or updated we need to update the package metadata
+ // Whenever a package is added or updated we need to update the package
+ // metadata
// bookkeeping.
dataChangedImpl(PACKAGE_MANAGER_SENTINEL);
} else {
if (!replacing) {
- // Outright removal. In the full-data case, the app will be dropped from the
+ // Outright removal. In the full-data case, the app will be dropped from
+ // the
// queue when its (now obsolete) name comes up again for backup.
synchronized (mBackupParticipants) {
removePackageParticipantsLocked(packageList, uid);
@@ -1324,12 +1404,19 @@
// Look for apps that define the android:backupAgent attribute
List<PackageInfo> targetApps = allAgentPackages();
if (packageNames != null) {
- if (MORE_DEBUG) Slog.v(TAG, "addPackageParticipantsLocked: #" + packageNames.length);
+ if (MORE_DEBUG) {
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "addPackageParticipantsLocked: #" + packageNames.length));
+ }
for (String packageName : packageNames) {
addPackageParticipantsLockedInner(packageName, targetApps);
}
} else {
- if (MORE_DEBUG) Slog.v(TAG, "addPackageParticipantsLocked: all");
+ if (MORE_DEBUG) {
+ Slog.v(TAG, addUserIdToLogMessage(mUserId, "addPackageParticipantsLocked: all"));
+ }
addPackageParticipantsLockedInner(null, targetApps);
}
}
@@ -1337,7 +1424,10 @@
private void addPackageParticipantsLockedInner(String packageName,
List<PackageInfo> targetPkgs) {
if (MORE_DEBUG) {
- Slog.v(TAG, "Examining " + packageName + " for backup agent");
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Examining " + packageName + " for backup agent"));
}
for (PackageInfo pkg : targetPkgs) {
@@ -1349,10 +1439,15 @@
mBackupParticipants.put(uid, set);
}
set.add(pkg.packageName);
- if (MORE_DEBUG) Slog.v(TAG, "Agent found; added");
+ if (MORE_DEBUG) Slog.v(TAG, addUserIdToLogMessage(mUserId, "Agent found; added"));
// Schedule a backup for it on general principles
- if (MORE_DEBUG) Slog.i(TAG, "Scheduling backup for new app " + pkg.packageName);
+ if (MORE_DEBUG) {
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Scheduling backup for new app " + pkg.packageName));
+ }
Message msg = mBackupHandler
.obtainMessage(MSG_SCHEDULE_BACKUP_PACKAGE, pkg.packageName);
mBackupHandler.sendMessage(msg);
@@ -1363,13 +1458,19 @@
// Remove the given packages' entries from our known active set.
private void removePackageParticipantsLocked(String[] packageNames, int oldUid) {
if (packageNames == null) {
- Slog.w(TAG, "removePackageParticipants with null list");
+ Slog.w(TAG, addUserIdToLogMessage(mUserId, "removePackageParticipants with null list"));
return;
}
if (MORE_DEBUG) {
- Slog.v(TAG, "removePackageParticipantsLocked: uid=" + oldUid
- + " #" + packageNames.length);
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "removePackageParticipantsLocked: uid="
+ + oldUid
+ + " #"
+ + packageNames.length));
}
for (String pkg : packageNames) {
// Known previous UID, so we know which package set to check
@@ -1377,7 +1478,12 @@
if (set != null && set.contains(pkg)) {
removePackageFromSetLocked(set, pkg);
if (set.isEmpty()) {
- if (MORE_DEBUG) Slog.v(TAG, " last one of this uid; purging set");
+ if (MORE_DEBUG) {
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, " last one of this uid; purging set"));
+ }
mBackupParticipants.remove(oldUid);
}
}
@@ -1393,7 +1499,11 @@
// Note that we deliberately leave it 'known' in the "ever backed up"
// bookkeeping so that its current-dataset data will be retrieved
// if the app is subsequently reinstalled
- if (MORE_DEBUG) Slog.v(TAG, " removing participant " + packageName);
+ if (MORE_DEBUG) {
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(mUserId, " removing participant " + packageName));
+ }
set.remove(packageName);
mPendingBackups.remove(packageName);
}
@@ -1467,14 +1577,19 @@
af.writeInt(-1);
} else {
af.writeInt(mAncestralPackages.size());
- if (DEBUG) Slog.v(TAG, "Ancestral packages: " + mAncestralPackages.size());
+ if (DEBUG) {
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Ancestral packages: " + mAncestralPackages.size()));
+ }
for (String pkgName : mAncestralPackages) {
af.writeUTF(pkgName);
- if (MORE_DEBUG) Slog.v(TAG, " " + pkgName);
+ if (MORE_DEBUG) Slog.v(TAG, addUserIdToLogMessage(mUserId, " " + pkgName));
}
}
} catch (IOException e) {
- Slog.w(TAG, "Unable to write token file:", e);
+ Slog.w(TAG, addUserIdToLogMessage(mUserId, "Unable to write token file:"), e);
}
}
@@ -1487,7 +1602,7 @@
mConnectedAgent = null;
try {
if (mActivityManager.bindBackupAgent(app.packageName, mode, mUserId)) {
- Slog.d(TAG, "awaiting agent for " + app);
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "awaiting agent for " + app));
// success; wait for the agent to arrive
// only wait 10 seconds for the bind to happen
@@ -1498,7 +1613,7 @@
mAgentConnectLock.wait(5000);
} catch (InterruptedException e) {
// just bail
- Slog.w(TAG, "Interrupted: " + e);
+ Slog.w(TAG, addUserIdToLogMessage(mUserId, "Interrupted: " + e));
mConnecting = false;
mConnectedAgent = null;
}
@@ -1506,10 +1621,14 @@
// if we timed out with no connect, abort and move on
if (mConnecting) {
- Slog.w(TAG, "Timeout waiting for agent " + app);
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(mUserId, "Timeout waiting for agent " + app));
mConnectedAgent = null;
}
- if (DEBUG) Slog.i(TAG, "got agent " + mConnectedAgent);
+ if (DEBUG) {
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "got agent " + mConnectedAgent));
+ }
agent = mConnectedAgent;
}
} catch (RemoteException e) {
@@ -1575,13 +1694,20 @@
if (!shouldClearData) {
if (MORE_DEBUG) {
- Slog.i(TAG, "Clearing app data is not allowed so not wiping "
- + packageName);
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Clearing app data is not allowed so not wiping "
+ + packageName));
}
return;
}
} catch (NameNotFoundException e) {
- Slog.w(TAG, "Tried to clear data for " + packageName + " but not found");
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Tried to clear data for " + packageName + " but not found"));
return;
}
@@ -1604,13 +1730,22 @@
} catch (InterruptedException e) {
// won't happen, but still.
mClearingData = false;
- Slog.w(TAG, "Interrupted while waiting for " + packageName
- + " data to be cleared", e);
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Interrupted while waiting for "
+ + packageName
+ + " data to be cleared"),
+ e);
}
}
if (mClearingData) {
- Slog.w(TAG, "Clearing app data for " + packageName + " timed out");
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Clearing app data for " + packageName + " timed out"));
}
}
}
@@ -1627,12 +1762,17 @@
synchronized (mQueueLock) {
if (mCurrentToken != 0 && mProcessedPackagesJournal.hasBeenProcessed(packageName)) {
if (MORE_DEBUG) {
- Slog.i(TAG, "App in ever-stored, so using current token");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "App in ever-stored, so using current token"));
}
token = mCurrentToken;
}
}
- if (MORE_DEBUG) Slog.i(TAG, "getAvailableRestoreToken() == " + token);
+ if (MORE_DEBUG) {
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "getAvailableRestoreToken() == " + token));
+ }
return token;
}
@@ -1654,7 +1794,7 @@
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "requestBackup");
if (packages == null || packages.length < 1) {
- Slog.e(TAG, "No packages named for backup request");
+ Slog.e(TAG, addUserIdToLogMessage(mUserId, "No packages named for backup request"));
BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
monitor = BackupManagerMonitorUtils.monitorEvent(monitor,
BackupManagerMonitor.LOG_EVENT_ID_NO_PACKAGES,
@@ -1665,10 +1805,10 @@
if (!mEnabled || !mSetupComplete) {
Slog.i(
TAG,
- "Backup requested but enabled="
+ addUserIdToLogMessage(mUserId, "Backup requested but enabled="
+ mEnabled
+ " setupComplete="
- + mSetupComplete);
+ + mSetupComplete));
BackupObserverUtils.sendBackupFinished(observer,
BackupManager.ERROR_BACKUP_NOT_ALLOWED);
final int logTag = mSetupComplete
@@ -1726,9 +1866,17 @@
EventLog.writeEvent(EventLogTags.BACKUP_REQUESTED, packages.length, kvBackupList.size(),
fullBackupList.size());
if (MORE_DEBUG) {
- Slog.i(TAG, "Backup requested for " + packages.length + " packages, of them: "
- + fullBackupList.size() + " full backups, " + kvBackupList.size()
- + " k/v backups");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Backup requested for "
+ + packages.length
+ + " packages, of them: "
+ + fullBackupList.size()
+ + " full backups, "
+ + kvBackupList.size()
+ + " k/v backups"));
}
boolean nonIncrementalBackup = (flags & BackupManager.FLAG_NON_INCREMENTAL_BACKUP) != 0;
@@ -1744,7 +1892,7 @@
public void cancelBackups() {
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "cancelBackups");
if (MORE_DEBUG) {
- Slog.i(TAG, "cancelBackups() called.");
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "cancelBackups() called."));
}
final long oldToken = Binder.clearCallingIdentity();
try {
@@ -1774,13 +1922,27 @@
public void prepareOperationTimeout(int token, long interval, BackupRestoreTask callback,
int operationType) {
if (operationType != OP_TYPE_BACKUP_WAIT && operationType != OP_TYPE_RESTORE_WAIT) {
- Slog.wtf(TAG, "prepareOperationTimeout() doesn't support operation "
- + Integer.toHexString(token) + " of type " + operationType);
+ Slog.wtf(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "prepareOperationTimeout() doesn't support operation "
+ + Integer.toHexString(token)
+ + " of type "
+ + operationType));
return;
}
if (MORE_DEBUG) {
- Slog.v(TAG, "starting timeout: token=" + Integer.toHexString(token)
- + " interval=" + interval + " callback=" + callback);
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "starting timeout: token="
+ + Integer.toHexString(token)
+ + " interval="
+ + interval
+ + " callback="
+ + callback));
}
synchronized (mCurrentOpLock) {
@@ -1798,8 +1960,12 @@
case OP_TYPE_RESTORE_WAIT:
return MSG_RESTORE_OPERATION_TIMEOUT;
default:
- Slog.wtf(TAG, "getMessageIdForOperationType called on invalid operation type: "
- + operationType);
+ Slog.wtf(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "getMessageIdForOperationType called on invalid operation type: "
+ + operationType));
return -1;
}
}
@@ -1810,8 +1976,14 @@
*/
public void putOperation(int token, Operation operation) {
if (MORE_DEBUG) {
- Slog.d(TAG, "Adding operation token=" + Integer.toHexString(token) + ", operation type="
- + operation.type);
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Adding operation token="
+ + Integer.toHexString(token)
+ + ", operation type="
+ + operation.type));
}
synchronized (mCurrentOpLock) {
mCurrentOperations.put(token, operation);
@@ -1824,12 +1996,15 @@
*/
public void removeOperation(int token) {
if (MORE_DEBUG) {
- Slog.d(TAG, "Removing operation token=" + Integer.toHexString(token));
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Removing operation token=" + Integer.toHexString(token)));
}
synchronized (mCurrentOpLock) {
if (mCurrentOperations.get(token) == null) {
- Slog.w(TAG, "Duplicate remove for operation. token="
- + Integer.toHexString(token));
+ Slog.w(TAG, addUserIdToLogMessage(mUserId, "Duplicate remove for operation. token="
+ + Integer.toHexString(token)));
}
mCurrentOperations.remove(token);
}
@@ -1838,8 +2013,8 @@
/** Block until we received an operation complete message (from the agent or cancellation). */
public boolean waitUntilOperationComplete(int token) {
if (MORE_DEBUG) {
- Slog.i(TAG, "Blocking until operation complete for "
- + Integer.toHexString(token));
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "Blocking until operation complete for "
+ + Integer.toHexString(token)));
}
int finalState = OP_PENDING;
Operation op = null;
@@ -1858,8 +2033,12 @@
// When the wait is notified we loop around and recheck the current state
} else {
if (MORE_DEBUG) {
- Slog.d(TAG, "Unblocked waiting for operation token="
- + Integer.toHexString(token));
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Unblocked waiting for operation token="
+ + Integer.toHexString(token)));
}
// No longer pending; we're done
finalState = op.state;
@@ -1874,8 +2053,8 @@
mBackupHandler.removeMessages(getMessageIdForOperationType(op.type));
}
if (MORE_DEBUG) {
- Slog.v(TAG, "operation " + Integer.toHexString(token)
- + " complete: finalState=" + finalState);
+ Slog.v(TAG, addUserIdToLogMessage(mUserId, "operation " + Integer.toHexString(token)
+ + " complete: finalState=" + finalState));
}
return finalState == OP_ACKNOWLEDGED;
}
@@ -1888,21 +2067,31 @@
op = mCurrentOperations.get(token);
if (MORE_DEBUG) {
if (op == null) {
- Slog.w(TAG, "Cancel of token " + Integer.toHexString(token)
- + " but no op found");
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Cancel of token "
+ + Integer.toHexString(token)
+ + " but no op found"));
}
}
int state = (op != null) ? op.state : OP_TIMEOUT;
if (state == OP_ACKNOWLEDGED) {
// The operation finished cleanly, so we have nothing more to do.
if (DEBUG) {
- Slog.w(TAG, "Operation already got an ack."
- + "Should have been removed from mCurrentOperations.");
+ Slog.w(TAG, addUserIdToLogMessage(mUserId, "Operation already got an ack."
+ + "Should have been removed from mCurrentOperations."));
}
op = null;
mCurrentOperations.delete(token);
} else if (state == OP_PENDING) {
- if (DEBUG) Slog.v(TAG, "Cancel: token=" + Integer.toHexString(token));
+ if (DEBUG) {
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Cancel: token=" + Integer.toHexString(token)));
+ }
op.state = OP_TIMEOUT;
// Can't delete op from mCurrentOperations here. waitUntilOperationComplete may be
// called after we receive cancel here. We need this op's state there.
@@ -1920,7 +2109,7 @@
// If there's a TimeoutHandler for this event, call it
if (op != null && op.callback != null) {
if (MORE_DEBUG) {
- Slog.v(TAG, " Invoking cancel on " + op.callback);
+ Slog.v(TAG, addUserIdToLogMessage(mUserId, " Invoking cancel on " + op.callback));
}
op.callback.handleCancel(cancelAll);
}
@@ -1955,13 +2144,20 @@
// manifest flag! TODO something less direct.
if (!UserHandle.isCore(app.uid)
&& !app.packageName.equals("com.android.backupconfirm")) {
- if (MORE_DEBUG) Slog.d(TAG, "Killing agent host process");
+ if (MORE_DEBUG) {
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Killing agent host process"));
+ }
mActivityManager.killApplicationProcess(app.processName, app.uid);
} else {
- if (MORE_DEBUG) Slog.d(TAG, "Not killing after operation: " + app.processName);
+ if (MORE_DEBUG) {
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Not killing after operation: " + app.processName));
+ }
}
} catch (RemoteException e) {
- Slog.d(TAG, "Lost app trying to shut down");
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Lost app trying to shut down"));
}
}
@@ -1975,7 +2171,12 @@
} catch (Exception e) {
// If we can't talk to the storagemanager service we have a serious problem; fail
// "secure" i.e. assuming that the device is encrypted.
- Slog.e(TAG, "Unable to communicate with storagemanager service: " + e.getMessage());
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Unable to communicate with storagemanager service: "
+ + e.getMessage()));
return true;
}
}
@@ -1999,7 +2200,10 @@
FullBackupJob.schedule(mUserId, mContext, latency, mConstants);
} else {
if (DEBUG_SCHEDULING) {
- Slog.i(TAG, "Full backup queue empty; not scheduling");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Full backup queue empty; not scheduling"));
}
}
}
@@ -2054,7 +2258,10 @@
private boolean fullBackupAllowable(String transportName) {
if (!mTransportManager.isTransportRegistered(transportName)) {
- Slog.w(TAG, "Transport not registered; full data backup not performed");
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Transport not registered; full data backup not performed"));
return false;
}
@@ -2066,12 +2273,19 @@
File pmState = new File(stateDir, PACKAGE_MANAGER_SENTINEL);
if (pmState.length() <= 0) {
if (DEBUG) {
- Slog.i(TAG, "Full backup requested but dataset not yet initialized");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Full backup requested but dataset not yet initialized"));
}
return false;
}
} catch (Exception e) {
- Slog.w(TAG, "Unable to get transport name: " + e.getMessage());
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Unable to get transport name: " + e.getMessage()));
return false;
}
@@ -2104,8 +2318,8 @@
// the job driving automatic backups; that job will be scheduled again when
// the user enables backup.
if (MORE_DEBUG) {
- Slog.i(TAG, "beginFullBackup but enabled=" + mEnabled
- + " setupComplete=" + mSetupComplete + "; ignoring");
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "beginFullBackup but enabled=" + mEnabled
+ + " setupComplete=" + mSetupComplete + "; ignoring"));
}
return false;
}
@@ -2115,19 +2329,29 @@
final PowerSaveState result =
mPowerManager.getPowerSaveState(ServiceType.FULL_BACKUP);
if (result.batterySaverEnabled) {
- if (DEBUG) Slog.i(TAG, "Deferring scheduled full backups in battery saver mode");
+ if (DEBUG) {
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Deferring scheduled full backups in battery saver mode"));
+ }
FullBackupJob.schedule(mUserId, mContext, keyValueBackupInterval, mConstants);
return false;
}
if (DEBUG_SCHEDULING) {
- Slog.i(TAG, "Beginning scheduled full backup operation");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(mUserId, "Beginning scheduled full backup operation"));
}
// Great; we're able to run full backup jobs now. See if we have any work to do.
synchronized (mQueueLock) {
if (mRunningFullBackupTask != null) {
- Slog.e(TAG, "Backup triggered but one already/still running!");
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Backup triggered but one already/still running!"));
return false;
}
@@ -2143,7 +2367,10 @@
if (mFullBackupQueue.size() == 0) {
// no work to do so just bow out
if (DEBUG) {
- Slog.i(TAG, "Backup queue empty; doing nothing");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Backup queue empty; doing nothing"));
}
runBackup = false;
break;
@@ -2154,7 +2381,10 @@
String transportName = mTransportManager.getCurrentTransportName();
if (!fullBackupAllowable(transportName)) {
if (MORE_DEBUG) {
- Slog.i(TAG, "Preconditions not met; not running full backup");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Preconditions not met; not running full backup"));
}
runBackup = false;
// Typically this means we haven't run a key/value backup yet. Back off
@@ -2170,7 +2400,11 @@
if (!runBackup) {
// It's too early to back up the next thing in the queue, so bow out
if (MORE_DEBUG) {
- Slog.i(TAG, "Device ready but too early to back up next app");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Device ready but too early to back up next app"));
}
// Wait until the next app in the queue falls due for a full data backup
latency = fullBackupInterval - timeSinceRun;
@@ -2185,8 +2419,14 @@
// so we cull it and force a loop around to consider the new head
// app.
if (MORE_DEBUG) {
- Slog.i(TAG, "Culling package " + entry.packageName
- + " in full-backup queue but not eligible");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Culling package "
+ + entry.packageName
+ + " in full-backup queue but not"
+ + " eligible"));
}
mFullBackupQueue.remove(0);
headBusy = true; // force the while() condition
@@ -2204,9 +2444,14 @@
+ mTokenGenerator.nextInt(BUSY_BACKOFF_FUZZ);
if (DEBUG_SCHEDULING) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- Slog.i(TAG, "Full backup time but " + entry.packageName
- + " is busy; deferring to "
- + sdf.format(new Date(nextEligible)));
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Full backup time but "
+ + entry.packageName
+ + " is busy; deferring to "
+ + sdf.format(new Date(nextEligible))));
}
// This relocates the app's entry from the head of the queue to
// its order-appropriate position further down, so upon looping
@@ -2225,7 +2470,11 @@
if (!runBackup) {
if (DEBUG_SCHEDULING) {
- Slog.i(TAG, "Nothing pending full backup; rescheduling +" + latency);
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Nothing pending full backup; rescheduling +" + latency));
}
final long deferTime = latency; // pin for the closure
FullBackupJob.schedule(mUserId, mContext, deferTime, mConstants);
@@ -2273,7 +2522,10 @@
}
if (pftbt != null) {
if (DEBUG_SCHEDULING) {
- Slog.i(TAG, "Telling running backup to stop");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Telling running backup to stop"));
}
pftbt.handleCancel(true);
}
@@ -2286,7 +2538,7 @@
public void restoreWidgetData(String packageName, byte[] widgetData) {
// Apply the restored widget state and generate the ID update for the app
if (MORE_DEBUG) {
- Slog.i(TAG, "Incorporating restored widget data");
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "Incorporating restored widget data"));
}
AppWidgetBackupBridge.restoreWidgetState(packageName, widgetData, mUserId);
}
@@ -2306,8 +2558,15 @@
// may share a uid, we need to note all candidates within that uid and schedule
// a backup pass for each of them.
if (targets == null) {
- Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
- + " uid=" + Binder.getCallingUid());
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "dataChanged but no participant pkg='"
+ + packageName
+ + "'"
+ + " uid="
+ + Binder.getCallingUid()));
return;
}
@@ -2318,7 +2577,12 @@
// one already there, then overwrite it, but no harm done.
BackupRequest req = new BackupRequest(packageName);
if (mPendingBackups.put(packageName, req) == null) {
- if (MORE_DEBUG) Slog.d(TAG, "Now staging backup of " + packageName);
+ if (MORE_DEBUG) {
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Now staging backup of " + packageName));
+ }
// Journal this request in case of crash. The put()
// operation returned null when this package was not already
@@ -2358,7 +2622,10 @@
if (mJournal == null) mJournal = DataChangedJournal.newJournal(mJournalDir);
mJournal.addPackage(str);
} catch (IOException e) {
- Slog.e(TAG, "Can't write " + str + " to backup journal", e);
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(mUserId, "Can't write " + str + " to backup journal"),
+ e);
mJournal = null;
}
}
@@ -2369,8 +2636,15 @@
public void dataChanged(final String packageName) {
final HashSet<String> targets = dataChangedTargets(packageName);
if (targets == null) {
- Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
- + " uid=" + Binder.getCallingUid());
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "dataChanged but no participant pkg='"
+ + packageName
+ + "'"
+ + " uid="
+ + Binder.getCallingUid()));
return;
}
@@ -2385,7 +2659,10 @@
public void initializeTransports(String[] transportNames, IBackupObserver observer) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"initializeTransport");
- Slog.v(TAG, "initializeTransport(): " + Arrays.asList(transportNames));
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "initializeTransport(): " + Arrays.asList(transportNames)));
final long oldId = Binder.clearCallingIdentity();
try {
@@ -2404,11 +2681,18 @@
public void setAncestralSerialNumber(long ancestralSerialNumber) {
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
"setAncestralSerialNumber");
- Slog.v(TAG, "Setting ancestral work profile id to " + ancestralSerialNumber);
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Setting ancestral work profile id to " + ancestralSerialNumber));
try (RandomAccessFile af = getAncestralSerialNumberFile()) {
af.writeLong(ancestralSerialNumber);
} catch (IOException e) {
- Slog.w(TAG, "Unable to write to work profile serial mapping file:", e);
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Unable to write to work profile serial mapping file:"),
+ e);
}
}
@@ -2420,7 +2704,11 @@
try (RandomAccessFile af = getAncestralSerialNumberFile()) {
return af.readLong();
} catch (IOException e) {
- Slog.w(TAG, "Unable to write to work profile serial number file:", e);
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Unable to write to work profile serial number file:"),
+ e);
return -1;
}
}
@@ -2443,13 +2731,24 @@
/** Clear the given package's backup data from the current transport. */
public void clearBackupData(String transportName, String packageName) {
- if (DEBUG) Slog.v(TAG, "clearBackupData() of " + packageName + " on " + transportName);
+ if (DEBUG) {
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "clearBackupData() of " + packageName + " on " + transportName));
+ }
+
PackageInfo info;
try {
info = mPackageManager.getPackageInfoAsUser(packageName,
PackageManager.GET_SIGNING_CERTIFICATES, mUserId);
} catch (NameNotFoundException e) {
- Slog.d(TAG, "No such package '" + packageName + "' - not clearing backup data");
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "No such package '" + packageName + "' - not clearing backup data"));
return;
}
@@ -2462,13 +2761,22 @@
} else {
// a caller with full permission can ask to back up any participating app
// !!! TODO: allow data-clear of ANY app?
- if (MORE_DEBUG) Slog.v(TAG, "Privileged caller, allowing clear of other apps");
+ if (MORE_DEBUG) {
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Privileged caller, allowing clear of other apps"));
+ }
apps = mProcessedPackagesJournal.getPackagesCopy();
}
if (apps.contains(packageName)) {
// found it; fire off the clear request
- if (MORE_DEBUG) Slog.v(TAG, "Found the app - running clear process");
+ if (MORE_DEBUG) {
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(mUserId, "Found the app - running clear process"));
+ }
mBackupHandler.removeMessages(MSG_RETRY_CLEAR);
synchronized (mQueueLock) {
TransportClient transportClient =
@@ -2507,24 +2815,36 @@
final PowerSaveState result =
mPowerManager.getPowerSaveState(ServiceType.KEYVALUE_BACKUP);
if (result.batterySaverEnabled) {
- if (DEBUG) Slog.v(TAG, "Not running backup while in battery save mode");
+ if (DEBUG) {
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Not running backup while in battery save mode"));
+ }
// Try again in several hours.
KeyValueBackupJob.schedule(mUserId, mContext, mConstants);
} else {
- if (DEBUG) Slog.v(TAG, "Scheduling immediate backup pass");
+ if (DEBUG) {
+ Slog.v(TAG, addUserIdToLogMessage(mUserId, "Scheduling immediate backup pass"));
+ }
synchronized (getQueueLock()) {
if (getPendingInits().size() > 0) {
// If there are pending init operations, we process those and then settle
// into the usual periodic backup schedule.
if (MORE_DEBUG) {
- Slog.v(TAG, "Init pending at scheduled backup");
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Init pending at scheduled backup"));
}
try {
getAlarmManager().cancel(mRunInitIntent);
mRunInitIntent.send();
} catch (PendingIntent.CanceledException ce) {
- Slog.w(TAG, "Run init intent cancelled");
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(mUserId, "Run init intent cancelled"));
}
return;
}
@@ -2534,8 +2854,8 @@
if (!isEnabled() || !isSetupComplete()) {
Slog.w(
TAG,
- "Backup pass but enabled=" + isEnabled()
- + " setupComplete=" + isSetupComplete());
+ addUserIdToLogMessage(mUserId, "Backup pass but enabled=" + isEnabled()
+ + " setupComplete=" + isSetupComplete()));
return;
}
@@ -2582,16 +2902,31 @@
long oldId = Binder.clearCallingIdentity();
try {
if (!mSetupComplete) {
- Slog.i(TAG, "Backup not supported before setup");
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "Backup not supported before setup"));
return;
}
if (DEBUG) {
- Slog.v(TAG, "Requesting backup: apks=" + includeApks + " obb=" + includeObbs
- + " shared=" + includeShared + " all=" + doAllApps + " system="
- + includeSystem + " includekeyvalue=" + doKeyValue + " pkgs=" + pkgList);
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Requesting backup: apks="
+ + includeApks
+ + " obb="
+ + includeObbs
+ + " shared="
+ + includeShared
+ + " all="
+ + doAllApps
+ + " system="
+ + includeSystem
+ + " includekeyvalue="
+ + doKeyValue
+ + " pkgs="
+ + pkgList));
}
- Slog.i(TAG, "Beginning adb backup...");
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "Beginning adb backup..."));
AdbBackupParams params = new AdbBackupParams(fd, includeApks, includeObbs,
includeShared, doWidgets, doAllApps, includeSystem, compress, doKeyValue,
@@ -2602,9 +2937,16 @@
}
// start up the confirmation UI
- if (DEBUG) Slog.d(TAG, "Starting backup confirmation UI, token=" + token);
+ if (DEBUG) {
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Starting backup confirmation UI, token=" + token));
+ }
if (!startConfirmationUi(token, FullBackup.FULL_BACKUP_INTENT_ACTION)) {
- Slog.e(TAG, "Unable to launch backup confirmation UI");
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(mUserId, "Unable to launch backup confirmation UI"));
mAdbBackupRestoreConfirmations.delete(token);
return;
}
@@ -2618,16 +2960,22 @@
startConfirmationTimeout(token, params);
// wait for the backup to be performed
- if (DEBUG) Slog.d(TAG, "Waiting for backup completion...");
+ if (DEBUG) {
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Waiting for backup completion..."));
+ }
waitForCompletion(params);
} finally {
try {
fd.close();
} catch (IOException e) {
- Slog.e(TAG, "IO error closing output for adb backup: " + e.getMessage());
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "IO error closing output for adb backup: " + e.getMessage()));
}
Binder.restoreCallingIdentity(oldId);
- Slog.d(TAG, "Adb backup processing complete.");
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Adb backup processing complete."));
}
}
@@ -2644,10 +2992,14 @@
String transportName = mTransportManager.getCurrentTransportName();
if (!fullBackupAllowable(transportName)) {
- Slog.i(TAG, "Full backup not currently possible -- key/value backup not yet run?");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Full backup not currently possible -- key/value backup not yet run?"));
} else {
if (DEBUG) {
- Slog.d(TAG, "fullTransportBackup()");
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "fullTransportBackup()"));
}
final long oldId = Binder.clearCallingIdentity();
@@ -2687,7 +3039,7 @@
}
if (DEBUG) {
- Slog.d(TAG, "Done with full transport backup.");
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Done with full transport backup."));
}
}
@@ -2707,11 +3059,13 @@
try {
if (!mSetupComplete) {
- Slog.i(TAG, "Full restore not permitted before setup");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(mUserId, "Full restore not permitted before setup"));
return;
}
- Slog.i(TAG, "Beginning restore...");
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "Beginning restore..."));
AdbRestoreParams params = new AdbRestoreParams(fd);
final int token = generateRandomIntegerToken();
@@ -2720,9 +3074,16 @@
}
// start up the confirmation UI
- if (DEBUG) Slog.d(TAG, "Starting restore confirmation UI, token=" + token);
+ if (DEBUG) {
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Starting restore confirmation UI, token=" + token));
+ }
if (!startConfirmationUi(token, FullBackup.FULL_RESTORE_INTENT_ACTION)) {
- Slog.e(TAG, "Unable to launch restore confirmation");
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(mUserId, "Unable to launch restore confirmation"));
mAdbBackupRestoreConfirmations.delete(token);
return;
}
@@ -2736,16 +3097,21 @@
startConfirmationTimeout(token, params);
// wait for the restore to be performed
- if (DEBUG) Slog.d(TAG, "Waiting for restore completion...");
+ if (DEBUG) {
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Waiting for restore completion..."));
+ }
waitForCompletion(params);
} finally {
try {
fd.close();
} catch (IOException e) {
- Slog.w(TAG, "Error trying to close fd after adb restore: " + e);
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Error trying to close fd after adb restore: " + e));
}
Binder.restoreCallingIdentity(oldId);
- Slog.i(TAG, "adb restore processing complete.");
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "adb restore processing complete."));
}
}
@@ -2773,8 +3139,8 @@
private void startConfirmationTimeout(int token, AdbParams params) {
if (MORE_DEBUG) {
- Slog.d(TAG, "Posting conf timeout msg after "
- + TIMEOUT_FULL_CONFIRMATION + " millis");
+ Slog.d(TAG, addUserIdToLogMessage(mUserId, "Posting conf timeout msg after "
+ + TIMEOUT_FULL_CONFIRMATION + " millis"));
}
Message msg = mBackupHandler.obtainMessage(MSG_FULL_CONFIRMATION_TIMEOUT,
token, 0, params);
@@ -2806,8 +3172,11 @@
public void acknowledgeAdbBackupOrRestore(int token, boolean allow,
String curPassword, String encPpassword, IFullBackupRestoreObserver observer) {
if (DEBUG) {
- Slog.d(TAG, "acknowledgeAdbBackupOrRestore : token=" + token
- + " allow=" + allow);
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "acknowledgeAdbBackupOrRestore : token=" + token + " allow=" + allow));
}
// TODO: possibly require not just this signature-only permission, but even
@@ -2835,17 +3204,29 @@
params.encryptPassword = encPpassword;
- if (MORE_DEBUG) Slog.d(TAG, "Sending conf message with verb " + verb);
+ if (MORE_DEBUG) {
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Sending conf message with verb " + verb));
+ }
mWakelock.acquire();
Message msg = mBackupHandler.obtainMessage(verb, params);
mBackupHandler.sendMessage(msg);
} else {
- Slog.w(TAG, "User rejected full backup/restore operation");
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "User rejected full backup/restore operation"));
// indicate completion without having actually transferred any data
signalAdbBackupRestoreCompletion(params);
}
} else {
- Slog.w(TAG, "Attempted to ack full backup/restore with invalid token");
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Attempted to ack full backup/restore with invalid token"));
}
}
} finally {
@@ -2858,7 +3239,7 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"setBackupEnabled");
- Slog.i(TAG, "Backup enabled => " + enable);
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "Backup enabled => " + enable));
long oldId = Binder.clearCallingIdentity();
try {
@@ -2875,7 +3256,9 @@
scheduleNextFullBackupJob(0);
} else if (!enable) {
// No longer enabled, so stop running backups
- if (MORE_DEBUG) Slog.i(TAG, "Opting out of backup");
+ if (MORE_DEBUG) {
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "Opting out of backup"));
+ }
KeyValueBackupJob.cancel(mUserId, mContext);
@@ -2891,12 +3274,15 @@
name -> {
final String dirName;
try {
- dirName =
- mTransportManager
- .getTransportDirName(name);
+ dirName = mTransportManager.getTransportDirName(name);
} catch (TransportNotRegisteredException e) {
// Should never happen
- Slog.e(TAG, "Unexpected unregistered transport", e);
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Unexpected unregistered transport"),
+ e);
return;
}
transportNames.add(name);
@@ -2925,7 +3311,7 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"setAutoRestore");
- Slog.i(TAG, "Auto restore => " + doAutoRestore);
+ Slog.i(TAG, addUserIdToLogMessage(mUserId, "Auto restore => " + doAutoRestore));
final long oldId = Binder.clearCallingIdentity();
try {
@@ -2951,7 +3337,12 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
"getCurrentTransport");
String currentTransport = mTransportManager.getCurrentTransportName();
- if (MORE_DEBUG) Slog.v(TAG, "... getCurrentTransport() returning " + currentTransport);
+ if (MORE_DEBUG) {
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "... getCurrentTransport() returning " + currentTransport));
+ }
return currentTransport;
}
@@ -3090,8 +3481,14 @@
try {
String previousTransportName = mTransportManager.selectTransport(transportName);
updateStateForTransport(transportName);
- Slog.v(TAG, "selectBackupTransport(transport = " + transportName
- + "): previous transport = " + previousTransportName);
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "selectBackupTransport(transport = "
+ + transportName
+ + "): previous transport = "
+ + previousTransportName));
return previousTransportName;
} finally {
Binder.restoreCallingIdentity(oldId);
@@ -3110,7 +3507,11 @@
final long oldId = Binder.clearCallingIdentity();
try {
String transportString = transportComponent.flattenToShortString();
- Slog.v(TAG, "selectBackupTransportAsync(transport = " + transportString + ")");
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "selectBackupTransportAsync(transport = " + transportString + ")"));
mBackupHandler.post(
() -> {
String transportName = null;
@@ -3122,7 +3523,10 @@
mTransportManager.getTransportName(transportComponent);
updateStateForTransport(transportName);
} catch (TransportNotRegisteredException e) {
- Slog.e(TAG, "Transport got unregistered");
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Transport got unregistered"));
result = BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
}
}
@@ -3134,7 +3538,12 @@
listener.onFailure(result);
}
} catch (RemoteException e) {
- Slog.e(TAG, "ISelectBackupTransportCallback listener not available");
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "ISelectBackupTransportCallback listener not"
+ + " available"));
}
});
} finally {
@@ -3159,11 +3568,23 @@
// Oops. We can't know the current dataset token, so reset and figure it out
// when we do the next k/v backup operation on this transport.
mCurrentToken = 0;
- Slog.w(TAG, "Transport " + newTransportName + " not available: current token = 0");
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Transport "
+ + newTransportName
+ + " not available: current token = 0"));
}
mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
} else {
- Slog.w(TAG, "Transport " + newTransportName + " not registered: current token = 0");
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Transport "
+ + newTransportName
+ + " not registered: current token = 0"));
// The named transport isn't registered, so we can't know what its current dataset token
// is. Reset as above.
mCurrentToken = 0;
@@ -3181,11 +3602,19 @@
try {
Intent intent = mTransportManager.getTransportConfigurationIntent(transportName);
if (MORE_DEBUG) {
- Slog.d(TAG, "getConfigurationIntent() returning intent " + intent);
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "getConfigurationIntent() returning intent " + intent));
}
return intent;
} catch (TransportNotRegisteredException e) {
- Slog.e(TAG, "Unable to get configuration intent from transport: " + e.getMessage());
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Unable to get configuration intent from transport: "
+ + e.getMessage()));
return null;
}
}
@@ -3206,11 +3635,18 @@
try {
String string = mTransportManager.getTransportCurrentDestinationString(transportName);
if (MORE_DEBUG) {
- Slog.d(TAG, "getDestinationString() returning " + string);
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "getDestinationString() returning " + string));
}
return string;
} catch (TransportNotRegisteredException e) {
- Slog.e(TAG, "Unable to get destination string from transport: " + e.getMessage());
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Unable to get destination string from transport: " + e.getMessage()));
return null;
}
}
@@ -3223,11 +3659,18 @@
try {
Intent intent = mTransportManager.getTransportDataManagementIntent(transportName);
if (MORE_DEBUG) {
- Slog.d(TAG, "getDataManagementIntent() returning intent " + intent);
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "getDataManagementIntent() returning intent " + intent));
}
return intent;
} catch (TransportNotRegisteredException e) {
- Slog.e(TAG, "Unable to get management intent from transport: " + e.getMessage());
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Unable to get management intent from transport: " + e.getMessage()));
return null;
}
}
@@ -3243,11 +3686,18 @@
try {
CharSequence label = mTransportManager.getTransportDataManagementLabel(transportName);
if (MORE_DEBUG) {
- Slog.d(TAG, "getDataManagementLabel() returning " + label);
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "getDataManagementLabel() returning " + label));
}
return label;
} catch (TransportNotRegisteredException e) {
- Slog.e(TAG, "Unable to get management label from transport: " + e.getMessage());
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Unable to get management label from transport: " + e.getMessage()));
return null;
}
}
@@ -3259,12 +3709,21 @@
public void agentConnected(String packageName, IBinder agentBinder) {
synchronized (mAgentConnectLock) {
if (Binder.getCallingUid() == Process.SYSTEM_UID) {
- Slog.d(TAG, "agentConnected pkg=" + packageName + " agent=" + agentBinder);
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "agentConnected pkg=" + packageName + " agent=" + agentBinder));
mConnectedAgent = IBackupAgent.Stub.asInterface(agentBinder);
mConnecting = false;
} else {
- Slog.w(TAG, "Non-system process uid=" + Binder.getCallingUid()
- + " claiming agent connected");
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Non-system process uid="
+ + Binder.getCallingUid()
+ + " claiming agent connected"));
}
mAgentConnectLock.notifyAll();
}
@@ -3282,8 +3741,13 @@
mConnectedAgent = null;
mConnecting = false;
} else {
- Slog.w(TAG, "Non-system process uid=" + Binder.getCallingUid()
- + " claiming agent disconnected");
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Non-system process uid="
+ + Binder.getCallingUid()
+ + " claiming agent disconnected"));
}
mAgentConnectLock.notifyAll();
}
@@ -3295,8 +3759,13 @@
*/
public void restoreAtInstall(String packageName, int token) {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- Slog.w(TAG, "Non-system process uid=" + Binder.getCallingUid()
- + " attemping install-time restore");
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Non-system process uid="
+ + Binder.getCallingUid()
+ + " attemping install-time restore"));
return;
}
@@ -3304,25 +3773,35 @@
long restoreSet = getAvailableRestoreToken(packageName);
if (DEBUG) {
- Slog.v(TAG, "restoreAtInstall pkg=" + packageName
- + " token=" + Integer.toHexString(token)
- + " restoreSet=" + Long.toHexString(restoreSet));
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "restoreAtInstall pkg="
+ + packageName
+ + " token="
+ + Integer.toHexString(token)
+ + " restoreSet="
+ + Long.toHexString(restoreSet)));
}
if (restoreSet == 0) {
- if (MORE_DEBUG) Slog.i(TAG, "No restore set");
+ if (MORE_DEBUG) Slog.i(TAG, addUserIdToLogMessage(mUserId, "No restore set"));
skip = true;
}
TransportClient transportClient =
mTransportManager.getCurrentTransportClient("BMS.restoreAtInstall()");
if (transportClient == null) {
- if (DEBUG) Slog.w(TAG, "No transport client");
+ if (DEBUG) Slog.w(TAG, addUserIdToLogMessage(mUserId, "No transport client"));
skip = true;
}
if (!mAutoRestore) {
if (DEBUG) {
- Slog.w(TAG, "Non-restorable state: auto=" + mAutoRestore);
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Non-restorable state: auto=" + mAutoRestore));
}
skip = true;
}
@@ -3341,7 +3820,9 @@
};
if (MORE_DEBUG) {
- Slog.d(TAG, "Restore at install of " + packageName);
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(mUserId, "Restore at install of " + packageName));
}
Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
msg.obj =
@@ -3356,7 +3837,10 @@
mBackupHandler.sendMessage(msg);
} catch (Exception e) {
// Calling into the transport broke; back off and proceed with the installation.
- Slog.e(TAG, "Unable to contact transport: " + e.getMessage());
+ Slog.e(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Unable to contact transport: " + e.getMessage()));
skip = true;
}
}
@@ -3370,7 +3854,7 @@
}
// Tell the PackageManager to proceed with the post-install handling for this package.
- if (DEBUG) Slog.v(TAG, "Finishing install immediately");
+ if (DEBUG) Slog.v(TAG, addUserIdToLogMessage(mUserId, "Finishing install immediately"));
try {
mPackageManagerBinder.finishPackageInstall(token, false);
} catch (RemoteException e) { /* can't happen */ }
@@ -3380,8 +3864,11 @@
/** Hand off a restore session. */
public IRestoreSession beginRestoreSession(String packageName, String transport) {
if (DEBUG) {
- Slog.v(TAG, "beginRestoreSession: pkg=" + packageName
- + " transport=" + transport);
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "beginRestoreSession: pkg=" + packageName + " transport=" + transport));
}
boolean needPermission = true;
@@ -3393,7 +3880,10 @@
try {
app = mPackageManager.getPackageInfoAsUser(packageName, 0, mUserId);
} catch (NameNotFoundException nnf) {
- Slog.w(TAG, "Asked to restore nonexistent pkg " + packageName);
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Asked to restore nonexistent pkg " + packageName));
throw new IllegalArgumentException("Package " + packageName + " not found");
}
@@ -3407,19 +3897,32 @@
}
if (needPermission) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
- "beginRestoreSession");
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.BACKUP, "beginRestoreSession");
} else {
- if (DEBUG) Slog.d(TAG, "restoring self on current transport; no permission needed");
+ if (DEBUG) {
+ Slog.d(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "restoring self on current transport; no permission needed"));
+ }
}
synchronized (this) {
if (mActiveRestoreSession != null) {
- Slog.i(TAG, "Restore session requested but one already active");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Restore session requested but one already active"));
return null;
}
if (mBackupRunning) {
- Slog.i(TAG, "Restore session requested but currently running backups");
+ Slog.i(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Restore session requested but currently running backups"));
return null;
}
mActiveRestoreSession = new ActiveRestoreSession(this, packageName, transport);
@@ -3433,9 +3936,14 @@
public void clearRestoreSession(ActiveRestoreSession currentSession) {
synchronized (this) {
if (currentSession != mActiveRestoreSession) {
- Slog.e(TAG, "ending non-current restore session");
+ Slog.e(TAG, addUserIdToLogMessage(mUserId, "ending non-current restore session"));
} else {
- if (DEBUG) Slog.v(TAG, "Clearing restore session and halting timeout");
+ if (DEBUG) {
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId, "Clearing restore session and halting timeout"));
+ }
mActiveRestoreSession = null;
mBackupHandler.removeMessages(MSG_RESTORE_SESSION_TIMEOUT);
}
@@ -3448,7 +3956,11 @@
*/
public void opComplete(int token, long result) {
if (MORE_DEBUG) {
- Slog.v(TAG, "opComplete: " + Integer.toHexString(token) + " result=" + result);
+ Slog.v(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "opComplete: " + Integer.toHexString(token) + " result=" + result));
}
Operation op = null;
synchronized (mCurrentOpLock) {
@@ -3461,8 +3973,12 @@
mCurrentOperations.delete(token);
} else if (op.state == OP_ACKNOWLEDGED) {
if (DEBUG) {
- Slog.w(TAG, "Received duplicate ack for token="
- + Integer.toHexString(token));
+ Slog.w(
+ TAG,
+ addUserIdToLogMessage(
+ mUserId,
+ "Received duplicate ack for token="
+ + Integer.toHexString(token)));
}
op = null;
mCurrentOperations.remove(token);
@@ -3606,7 +4122,7 @@
" " + f.getName() + " - " + f.length() + " state bytes");
}
} catch (Exception e) {
- Slog.e(TAG, "Error in transport", e);
+ Slog.e(TAG, addUserIdToLogMessage(mUserId, "Error in transport"), e);
pw.println(" Error: " + e);
}
}
@@ -3665,6 +4181,10 @@
}
}
+ private static String addUserIdToLogMessage(int userId, String message) {
+ return "[UserID:" + userId + "] " + message;
+ }
+
public IBackupManager getBackupManagerBinder() {
return mBackupManagerBinder;
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 9fddafb..7d85966 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -66,7 +66,6 @@
public static final int PACKAGE_CONFIGURATOR = 9;
public static final int PACKAGE_INCIDENT_REPORT_APPROVER = 10;
public static final int PACKAGE_APP_PREDICTOR = 11;
- public static final int PACKAGE_TELEPHONY = 12;
public static final int PACKAGE_WIFI = 13;
public static final int PACKAGE_COMPANION = 14;
public static final int PACKAGE_RETAIL_DEMO = 15;
@@ -124,7 +123,6 @@
PACKAGE_CONFIGURATOR,
PACKAGE_INCIDENT_REPORT_APPROVER,
PACKAGE_APP_PREDICTOR,
- PACKAGE_TELEPHONY,
PACKAGE_WIFI,
PACKAGE_COMPANION,
PACKAGE_RETAIL_DEMO,
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3a3358c..91dd1d5 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -110,6 +110,7 @@
import android.net.PrivateDnsConfigParcel;
import android.net.ProxyInfo;
import android.net.RouteInfo;
+import android.net.RouteInfoParcel;
import android.net.SocketKeepalive;
import android.net.TetheringManager;
import android.net.UidRange;
@@ -120,6 +121,7 @@
import android.net.metrics.NetworkEvent;
import android.net.netlink.InetDiagMessage;
import android.net.shared.PrivateDnsConfig;
+import android.net.util.LinkPropertiesUtils.CompareOrUpdateResult;
import android.net.util.LinkPropertiesUtils.CompareResult;
import android.net.util.MultinetworkPolicyTracker;
import android.net.util.NetdService;
@@ -232,6 +234,7 @@
import java.util.StringJoiner;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
/**
* @hide
@@ -1666,7 +1669,7 @@
if (newNc.getNetworkSpecifier() != null) {
newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact());
}
- newNc.setAdministratorUids(Collections.EMPTY_LIST);
+ newNc.setAdministratorUids(new int[0]);
return newNc;
}
@@ -1710,7 +1713,7 @@
}
if (checkSettingsPermission(callerPid, callerUid)) {
- return lp.makeSensitiveFieldsParcelingCopy();
+ return new LinkProperties(lp, true /* parcelSensitiveFields */);
}
final LinkProperties newLp = new LinkProperties(lp);
@@ -1727,7 +1730,7 @@
nc.setSingleUid(callerUid);
}
nc.setRequestorUidAndPackageName(callerUid, callerPackageName);
- nc.setAdministratorUids(Collections.EMPTY_LIST);
+ nc.setAdministratorUids(new int[0]);
// Clear owner UID; this can never come from an app.
nc.setOwnerUid(INVALID_UID);
@@ -2237,14 +2240,9 @@
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
final NetworkInfo ni = intent.getParcelableExtra(
ConnectivityManager.EXTRA_NETWORK_INFO);
- if (ni.getType() == ConnectivityManager.TYPE_MOBILE_SUPL) {
- intent.setAction(ConnectivityManager.CONNECTIVITY_ACTION_SUPL);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- } else {
- BroadcastOptions opts = BroadcastOptions.makeBasic();
- opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M);
- options = opts.toBundle();
- }
+ final BroadcastOptions opts = BroadcastOptions.makeBasic();
+ opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M);
+ options = opts.toBundle();
final IBatteryStats bs = mDeps.getBatteryStatsService();
try {
bs.noteConnectivityChanged(intent.getIntExtra(
@@ -5951,15 +5949,49 @@
}
}
+ // TODO: move to frameworks/libs/net.
+ private RouteInfoParcel convertRouteInfo(RouteInfo route) {
+ final String nextHop;
+
+ switch (route.getType()) {
+ case RouteInfo.RTN_UNICAST:
+ if (route.hasGateway()) {
+ nextHop = route.getGateway().getHostAddress();
+ } else {
+ nextHop = INetd.NEXTHOP_NONE;
+ }
+ break;
+ case RouteInfo.RTN_UNREACHABLE:
+ nextHop = INetd.NEXTHOP_UNREACHABLE;
+ break;
+ case RouteInfo.RTN_THROW:
+ nextHop = INetd.NEXTHOP_THROW;
+ break;
+ default:
+ nextHop = INetd.NEXTHOP_NONE;
+ break;
+ }
+
+ final RouteInfoParcel rip = new RouteInfoParcel();
+ rip.ifName = route.getInterface();
+ rip.destination = route.getDestination().toString();
+ rip.nextHop = nextHop;
+ rip.mtu = route.getMtu();
+
+ return rip;
+ }
+
/**
* Have netd update routes from oldLp to newLp.
* @return true if routes changed between oldLp and newLp
*/
private boolean updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId) {
- // Compare the route diff to determine which routes should be added and removed.
- CompareResult<RouteInfo> routeDiff = new CompareResult<>(
+ Function<RouteInfo, IpPrefix> getDestination = (r) -> r.getDestination();
+ // compare the route diff to determine which routes have been updated
+ CompareOrUpdateResult<IpPrefix, RouteInfo> routeDiff = new CompareOrUpdateResult<>(
oldLp != null ? oldLp.getAllRoutes() : null,
- newLp != null ? newLp.getAllRoutes() : null);
+ newLp != null ? newLp.getAllRoutes() : null,
+ getDestination);
// add routes before removing old in case it helps with continuous connectivity
@@ -5968,10 +6000,10 @@
if (route.hasGateway()) continue;
if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
try {
- mNMS.addRoute(netId, route);
+ mNetd.networkAddRouteParcel(netId, convertRouteInfo(route));
} catch (Exception e) {
if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) {
- loge("Exception in addRoute for non-gateway: " + e);
+ loge("Exception in networkAddRouteParcel for non-gateway: " + e);
}
}
}
@@ -5979,10 +6011,10 @@
if (!route.hasGateway()) continue;
if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
try {
- mNMS.addRoute(netId, route);
+ mNetd.networkAddRouteParcel(netId, convertRouteInfo(route));
} catch (Exception e) {
if ((route.getGateway() instanceof Inet4Address) || VDBG) {
- loge("Exception in addRoute for gateway: " + e);
+ loge("Exception in networkAddRouteParcel for gateway: " + e);
}
}
}
@@ -5990,12 +6022,22 @@
for (RouteInfo route : routeDiff.removed) {
if (VDBG || DDBG) log("Removing Route [" + route + "] from network " + netId);
try {
- mNMS.removeRoute(netId, route);
+ mNetd.networkRemoveRouteParcel(netId, convertRouteInfo(route));
} catch (Exception e) {
- loge("Exception in removeRoute: " + e);
+ loge("Exception in networkRemoveRouteParcel: " + e);
}
}
- return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty();
+
+ for (RouteInfo route : routeDiff.updated) {
+ if (VDBG || DDBG) log("Updating Route [" + route + "] from network " + netId);
+ try {
+ mNetd.networkUpdateRouteParcel(netId, convertRouteInfo(route));
+ } catch (Exception e) {
+ loge("Exception in networkUpdateRouteParcel: " + e);
+ }
+ }
+ return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty()
+ || !routeDiff.updated.isEmpty();
}
private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId) {
@@ -7817,7 +7859,7 @@
getMatchingPermissionedCallbacks(nai);
for (final IConnectivityDiagnosticsCallback cb : results) {
try {
- cb.onConnectivityReport(report);
+ cb.onConnectivityReportAvailable(report);
} catch (RemoteException ex) {
loge("Error invoking onConnectivityReport", ex);
}
@@ -7864,7 +7906,7 @@
private void clearNetworkCapabilitiesUids(@NonNull NetworkCapabilities nc) {
nc.setUids(null);
- nc.setAdministratorUids(Collections.EMPTY_LIST);
+ nc.setAdministratorUids(new int[0]);
nc.setOwnerUid(Process.INVALID_UID);
}
@@ -7892,8 +7934,15 @@
return true;
}
- if (!mLocationPermissionChecker.checkLocationPermission(
- callbackPackageName, null /* featureId */, callbackUid, null /* message */)) {
+ // LocationPermissionChecker#checkLocationPermission can throw SecurityException if the uid
+ // and package name don't match. Throwing on the CS thread is not acceptable, so wrap the
+ // call in a try-catch.
+ try {
+ if (!mLocationPermissionChecker.checkLocationPermission(
+ callbackPackageName, null /* featureId */, callbackUid, null /* message */)) {
+ return false;
+ }
+ } catch (SecurityException e) {
return false;
}
@@ -7904,8 +7953,9 @@
}
// Administrator UIDs also contains the Owner UID
- if (nai.networkCapabilities.getAdministratorUids().contains(callbackUid)) {
- return true;
+ final int[] administratorUids = nai.networkCapabilities.getAdministratorUids();
+ for (final int uid : administratorUids) {
+ if (uid == callbackUid) return true;
}
return false;
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 52a1b5a..41a104c 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -161,6 +161,9 @@
private final Runnable mSaveToFile = this::saveToFile;
private final SystemClock mSystemClock;
private final BootThreshold mBootThreshold;
+ // The set of packages that have been synced with the ExplicitHealthCheckController
+ @GuardedBy("mLock")
+ private Set<String> mRequestedHealthCheckPackages = new ArraySet<>();
@GuardedBy("mLock")
private boolean mIsPackagesReady;
// Flag to control whether explicit health checks are supported or not
@@ -174,6 +177,9 @@
// 0 if no prune is scheduled.
@GuardedBy("mLock")
private long mUptimeAtLastStateSync;
+ // If true, sync explicit health check packages with the ExplicitHealthCheckController.
+ @GuardedBy("mLock")
+ private boolean mSyncRequired = false;
@FunctionalInterface
@VisibleForTesting
@@ -249,6 +255,7 @@
*/
public void registerHealthObserver(PackageHealthObserver observer) {
synchronized (mLock) {
+ mSyncRequired = true;
ObserverInternal internalObserver = mAllObservers.get(observer.getName());
if (internalObserver != null) {
internalObserver.registeredObserver = observer;
@@ -628,17 +635,23 @@
* @see #syncRequestsAsync
*/
private void syncRequests() {
- Set<String> packages = null;
+ boolean syncRequired = false;
synchronized (mLock) {
if (mIsPackagesReady) {
- packages = getPackagesPendingHealthChecksLocked();
+ Set<String> packages = getPackagesPendingHealthChecksLocked();
+ if (!packages.equals(mRequestedHealthCheckPackages) || mSyncRequired) {
+ syncRequired = true;
+ mRequestedHealthCheckPackages = packages;
+ }
} // else, we will sync requests when packages become ready
}
// Call outside lock to avoid holding lock when calling into the controller.
- if (packages != null) {
- Slog.i(TAG, "Syncing health check requests for packages: " + packages);
- mHealthCheckController.syncRequests(packages);
+ if (syncRequired) {
+ Slog.i(TAG, "Syncing health check requests for packages: "
+ + mRequestedHealthCheckPackages);
+ mHealthCheckController.syncRequests(mRequestedHealthCheckPackages);
+ mSyncRequired = false;
}
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 2c220d3..a767347 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -4076,7 +4076,7 @@
return Zygote.MOUNT_EXTERNAL_NONE;
}
- if (mIsFuseEnabled && mMediaStoreAuthorityAppId == UserHandle.getAppId(uid)) {
+ if (mIsFuseEnabled && mStorageManagerInternal.isExternalStorageService(uid)) {
// Determine if caller requires pass_through mount; note that we do this for
// all processes that share a UID with MediaProvider; but this is fine, since
// those processes anyway share the same rights as MediaProvider.
@@ -4139,19 +4139,6 @@
boolean hasLegacy = mIAppOpsService.checkOperation(OP_LEGACY_STORAGE,
uid, packageName) == MODE_ALLOWED;
- // Hack(b/147137425): we have to honor hasRequestedLegacyExternalStorage for a short
- // while to enable 2 cases.
- // 1) Apps that want to be in scoped storage in R, but want to opt out in Q devices,
- // because they want to use raw file paths, would fail until fuse is enabled by default.
- // 2) Test apps that target current sdk will fail. They would fail even after fuse is
- // enabled, but we are fixing it with b/142395442. We are not planning to enable
- // fuse by default until b/142395442 is fixed.
- if (!hasLegacy && !mIsFuseEnabled) {
- ApplicationInfo ai = mIPackageManager.getApplicationInfo(packageName,
- 0, UserHandle.getUserId(uid));
- hasLegacy = (ai != null && ai.hasRequestedLegacyExternalStorage());
- }
-
if (hasLegacy && hasWrite) {
return Zygote.MOUNT_EXTERNAL_WRITE;
} else if (hasLegacy && hasRead) {
@@ -4422,14 +4409,16 @@
String.format("/storage/emulated/%d/Android/data/%s/",
userId, pkg);
+ int appUid =
+ UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
// Create package obb and data dir if it doesn't exist.
File file = new File(packageObbDir);
if (!file.exists()) {
- vold.setupAppDir(packageObbDir, mPmInternal.getPackage(pkg).getUid());
+ vold.setupAppDir(packageObbDir, appUid);
}
file = new File(packageDataDir);
if (!file.exists()) {
- vold.setupAppDir(packageDataDir, mPmInternal.getPackage(pkg).getUid());
+ vold.setupAppDir(packageDataDir, appUid);
}
}
} catch (ServiceManager.ServiceNotFoundException | RemoteException e) {
@@ -4524,6 +4513,11 @@
}
}
+ @Override
+ public boolean isExternalStorageService(int uid) {
+ return mMediaStoreAuthorityAppId == UserHandle.getAppId(uid);
+ }
+
public boolean hasExternalStorage(int uid, String packageName) {
// No need to check for system uid. This avoids a deadlock between
// PackageManagerService and AppOpsService.
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index 35a9802..81a1372 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -230,6 +230,7 @@
@Nullable LinkProperties lp,
boolean isMetered,
int callingUid,
+ @NonNull int[] administratorUids,
@NonNull IBinder binder)
throws RemoteException, SocketException {
Objects.requireNonNull(looper, "missing Looper");
@@ -248,6 +249,7 @@
nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
nc.setNetworkSpecifier(new StringNetworkSpecifier(iface));
+ nc.setAdministratorUids(administratorUids);
if (!isMetered) {
nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
}
@@ -301,6 +303,7 @@
@NonNull String iface,
@Nullable LinkProperties lp,
boolean isMetered,
+ @NonNull int[] administratorUids,
@NonNull IBinder binder) {
enforceTestNetworkPermissions(mContext);
@@ -335,6 +338,7 @@
lp,
isMetered,
callingUid,
+ administratorUids,
binder);
mTestNetworkTracker.put(agent.getNetwork().netId, agent);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4485af1..a458498 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -579,6 +579,13 @@
static final String EXTRA_DESCRIPTION = "android.intent.extra.DESCRIPTION";
static final String EXTRA_BUGREPORT_TYPE = "android.intent.extra.BUGREPORT_TYPE";
+ /**
+ * The maximum number of bytes that {@link #setProcessStateSummary} accepts.
+ *
+ * @see {@link android.app.ActivityManager#setProcessStateSummary(byte[])}
+ */
+ static final int MAX_STATE_DATA_SIZE = 128;
+
/** All system services */
SystemServiceManager mSystemServiceManager;
@@ -2179,9 +2186,17 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+ Process.enableFreezer(false);
+ }
+
if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
"meminfo", pw)) return;
PriorityDump.dump(mPriorityDumper, fd, pw, args);
+
+ if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+ Process.enableFreezer(true);
+ }
}
}
@@ -2193,9 +2208,17 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+ Process.enableFreezer(false);
+ }
+
if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
"gfxinfo", pw)) return;
mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
+
+ if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+ Process.enableFreezer(true);
+ }
}
}
@@ -2207,9 +2230,17 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+ Process.enableFreezer(false);
+ }
+
if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
"dbinfo", pw)) return;
mActivityManagerService.dumpDbInfo(fd, pw, args);
+
+ if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
+ Process.enableFreezer(true);
+ }
}
}
@@ -3178,7 +3209,7 @@
return mAtmInternal.compatibilityInfoForPackage(ai);
}
- private void enforceNotIsolatedCaller(String caller) {
+ /* package */ void enforceNotIsolatedCaller(String caller) {
if (UserHandle.isIsolated(Binder.getCallingUid())) {
throw new SecurityException("Isolated process not allowed to call " + caller);
}
@@ -3863,6 +3894,18 @@
public static File dumpStackTraces(ArrayList<Integer> firstPids,
ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids,
ArrayList<Integer> nativePids, StringWriter logExceptionCreatingFile) {
+ return dumpStackTraces(firstPids, processCpuTracker, lastPids, nativePids,
+ logExceptionCreatingFile, null);
+ }
+
+ /**
+ * @param firstPidOffsets Optional, when it's set, it receives the start/end offset
+ * of the very first pid to be dumped.
+ */
+ /* package */ static File dumpStackTraces(ArrayList<Integer> firstPids,
+ ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids,
+ ArrayList<Integer> nativePids, StringWriter logExceptionCreatingFile,
+ long[] firstPidOffsets) {
ArrayList<Integer> extraPids = null;
Slog.i(TAG, "dumpStackTraces pids=" + lastPids + " nativepids=" + nativePids);
@@ -3914,12 +3957,22 @@
return null;
}
- dumpStackTraces(tracesFile.getAbsolutePath(), firstPids, nativePids, extraPids);
+ Pair<Long, Long> offsets = dumpStackTraces(
+ tracesFile.getAbsolutePath(), firstPids, nativePids, extraPids);
+ if (firstPidOffsets != null) {
+ if (offsets == null) {
+ firstPidOffsets[0] = firstPidOffsets[1] = -1;
+ } else {
+ firstPidOffsets[0] = offsets.first; // Start offset to the ANR trace file
+ firstPidOffsets[1] = offsets.second; // End offset to the ANR trace file
+ }
+ }
return tracesFile;
}
@GuardedBy("ActivityManagerService.class")
private static SimpleDateFormat sAnrFileDateFormat;
+ static final String ANR_FILE_PREFIX = "anr_";
private static synchronized File createAnrDumpFile(File tracesDir) throws IOException {
if (sAnrFileDateFormat == null) {
@@ -3927,7 +3980,7 @@
}
final String formattedDate = sAnrFileDateFormat.format(new Date());
- final File anrFile = new File(tracesDir, "anr_" + formattedDate);
+ final File anrFile = new File(tracesDir, ANR_FILE_PREFIX + formattedDate);
if (anrFile.createNewFile()) {
FileUtils.setPermissions(anrFile.getAbsolutePath(), 0600, -1, -1); // -rw-------
@@ -3996,7 +4049,10 @@
return SystemClock.elapsedRealtime() - timeStart;
}
- public static void dumpStackTraces(String tracesFile, ArrayList<Integer> firstPids,
+ /**
+ * @return The start/end offset of the trace of the very first PID
+ */
+ public static Pair<Long, Long> dumpStackTraces(String tracesFile, ArrayList<Integer> firstPids,
ArrayList<Integer> nativePids, ArrayList<Integer> extraPids) {
Slog.i(TAG, "Dumping to " + tracesFile);
@@ -4008,21 +4064,39 @@
// We must complete all stack dumps within 20 seconds.
long remainingTime = 20 * 1000;
+ // As applications are usually interested with the ANR stack traces, but we can't share with
+ // them the stack traces other than their own stacks. So after the very first PID is
+ // dumped, remember the current file size.
+ long firstPidStart = -1;
+ long firstPidEnd = -1;
+
// First collect all of the stacks of the most important pids.
if (firstPids != null) {
int num = firstPids.size();
for (int i = 0; i < num; i++) {
- Slog.i(TAG, "Collecting stacks for pid " + firstPids.get(i));
- final long timeTaken = dumpJavaTracesTombstoned(firstPids.get(i), tracesFile,
+ final int pid = firstPids.get(i);
+ // We don't copy ANR traces from the system_server intentionally.
+ final boolean firstPid = i == 0 && MY_PID != pid;
+ File tf = null;
+ if (firstPid) {
+ tf = new File(tracesFile);
+ firstPidStart = tf.exists() ? tf.length() : 0;
+ }
+
+ Slog.i(TAG, "Collecting stacks for pid " + pid);
+ final long timeTaken = dumpJavaTracesTombstoned(pid, tracesFile,
remainingTime);
remainingTime -= timeTaken;
if (remainingTime <= 0) {
- Slog.e(TAG, "Aborting stack trace dump (current firstPid=" + firstPids.get(i) +
- "); deadline exceeded.");
- return;
+ Slog.e(TAG, "Aborting stack trace dump (current firstPid=" + pid
+ + "); deadline exceeded.");
+ return firstPidStart >= 0 ? new Pair<>(firstPidStart, firstPidEnd) : null;
}
+ if (firstPid) {
+ firstPidEnd = tf.length();
+ }
if (DEBUG_ANR) {
Slog.d(TAG, "Done with pid " + firstPids.get(i) + " in " + timeTaken + "ms");
}
@@ -4044,7 +4118,7 @@
if (remainingTime <= 0) {
Slog.e(TAG, "Aborting stack trace dump (current native pid=" + pid +
"); deadline exceeded.");
- return;
+ return firstPidStart >= 0 ? new Pair<>(firstPidStart, firstPidEnd) : null;
}
if (DEBUG_ANR) {
@@ -4064,7 +4138,7 @@
if (remainingTime <= 0) {
Slog.e(TAG, "Aborting stack trace dump (current extra pid=" + pid +
"); deadline exceeded.");
- return;
+ return firstPidStart >= 0 ? new Pair<>(firstPidStart, firstPidEnd) : null;
}
if (DEBUG_ANR) {
@@ -4073,6 +4147,7 @@
}
}
Slog.i(TAG, "Done dumping");
+ return firstPidStart >= 0 ? new Pair<>(firstPidStart, firstPidEnd) : null;
}
@Override
@@ -10256,6 +10331,15 @@
return new ParceledListSlice<ApplicationExitInfo>(results);
}
+ @Override
+ public void setProcessStateSummary(@Nullable byte[] state) {
+ if (state != null && state.length > MAX_STATE_DATA_SIZE) {
+ throw new IllegalArgumentException("Data size is too large");
+ }
+ mProcessList.mAppExitInfoTracker.setProcessStateSummary(Binder.getCallingUid(),
+ Binder.getCallingPid(), state);
+ }
+
/**
* Check if the calling process has the permission to dump given package,
* throw SecurityException if it doesn't have the permission.
@@ -10263,7 +10347,7 @@
* @return The UID of the given package, or {@link android.os.Process#INVALID_UID}
* if the package is not found.
*/
- private int enforceDumpPermissionForPackage(String packageName, int userId, int callingUid,
+ int enforceDumpPermissionForPackage(String packageName, int userId, int callingUid,
String function) {
long identity = Binder.clearCallingIdentity();
int uid = Process.INVALID_UID;
@@ -19818,6 +19902,7 @@
void setPermissions(@Nullable String[] permissions) {
mPermissions = permissions;
+ PackageManager.invalidatePackageInfoCache();
}
@Override
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index 028a059..0c3d02d 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -17,23 +17,31 @@
package com.android.server.am;
import static android.app.ActivityManager.RunningAppProcessInfo.procStateToImportance;
+import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import android.annotation.Nullable;
import android.app.ApplicationExitInfo;
import android.app.ApplicationExitInfo.Reason;
import android.app.ApplicationExitInfo.SubReason;
+import android.app.IAppTraceRetriever;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.icu.text.SimpleDateFormat;
+import android.os.Binder;
+import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.system.OsConstants;
@@ -52,12 +60,17 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ProcessMap;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.IoThread;
import com.android.server.ServiceThread;
import com.android.server.SystemServiceManager;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
@@ -68,6 +81,10 @@
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.zip.GZIPOutputStream;
/**
* A class to manage all the {@link android.app.ApplicationExitInfo} records.
@@ -80,16 +97,21 @@
*/
private static final long APP_EXIT_INFO_PERSIST_INTERVAL = TimeUnit.MINUTES.toMillis(30);
- /** These are actions that the forEachPackage should take after each iteration */
+ /** These are actions that the forEach* should take after each iteration */
private static final int FOREACH_ACTION_NONE = 0;
- private static final int FOREACH_ACTION_REMOVE_PACKAGE = 1;
+ private static final int FOREACH_ACTION_REMOVE_ITEM = 1;
private static final int FOREACH_ACTION_STOP_ITERATION = 2;
private static final int APP_EXIT_RAW_INFO_POOL_SIZE = 8;
@VisibleForTesting
+ static final String APP_EXIT_STORE_DIR = "procexitstore";
+
+ @VisibleForTesting
static final String APP_EXIT_INFO_FILE = "procexitinfo";
+ private static final String APP_TRACE_FILE_SUFFIX = ".gz";
+
private final Object mLock = new Object();
/**
@@ -153,6 +175,13 @@
final ArrayList<ApplicationExitInfo> mTmpInfoList2 = new ArrayList<ApplicationExitInfo>();
/**
+ * The path to the directory which includes the historical proc exit info file
+ * as specified in {@link #mProcExitInfoFile}, as well as the associated trace files.
+ */
+ @VisibleForTesting
+ File mProcExitStoreDir;
+
+ /**
* The path to the historical proc exit info file, persisted in the storage.
*/
@VisibleForTesting
@@ -176,6 +205,35 @@
final AppExitInfoExternalSource mAppExitInfoSourceLmkd =
new AppExitInfoExternalSource("lmkd", ApplicationExitInfo.REASON_LOW_MEMORY);
+ /**
+ * The active per-UID/PID state data set by
+ * {@link android.app.ActivityManager#setProcessStateSummary};
+ * these state data are to be "claimed" when its process dies, by then the data will be moved
+ * from this list to the new instance of ApplicationExitInfo.
+ *
+ * <p> The mapping here is UID -> PID -> state </p>
+ *
+ * @see android.app.ActivityManager#setProcessStateSummary(byte[])
+ */
+ @GuardedBy("mLock")
+ final SparseArray<SparseArray<byte[]>> mActiveAppStateSummary = new SparseArray<>();
+
+ /**
+ * The active per-UID/PID trace file when an ANR occurs but the process hasn't been killed yet,
+ * each record is a path to the actual trace file; these files are to be "claimed"
+ * when its process dies, by then the "ownership" of the files will be transferred
+ * from this list to the new instance of ApplicationExitInfo.
+ *
+ * <p> The mapping here is UID -> PID -> file </p>
+ */
+ @GuardedBy("mLock")
+ final SparseArray<SparseArray<File>> mActiveAppTraces = new SparseArray<>();
+
+ /**
+ * The implementation of the interface IAppTraceRetriever.
+ */
+ final AppTraceRetriever mAppTraceRetriever = new AppTraceRetriever();
+
AppExitInfoTracker() {
mData = new ProcessMap<AppExitInfoContainer>();
mRawRecordsPool = new SynchronizedPool<ApplicationExitInfo>(APP_EXIT_RAW_INFO_POOL_SIZE);
@@ -187,7 +245,13 @@
THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
thread.start();
mKillHandler = new KillHandler(thread.getLooper());
- mProcExitInfoFile = new File(SystemServiceManager.ensureSystemDir(), APP_EXIT_INFO_FILE);
+
+ mProcExitStoreDir = new File(SystemServiceManager.ensureSystemDir(), APP_EXIT_STORE_DIR);
+ if (!FileUtils.createDir(mProcExitStoreDir)) {
+ Slog.e(TAG, "Unable to create " + mProcExitStoreDir);
+ return;
+ }
+ mProcExitInfoFile = new File(mProcExitStoreDir, APP_EXIT_INFO_FILE);
mAppExitInfoHistoryListSize = service.mContext.getResources().getInteger(
com.android.internal.R.integer.config_app_exit_info_history_list_size);
@@ -304,7 +368,7 @@
+ "(" + raw.getPid() + "/u" + raw.getRealUid() + ")");
}
- ApplicationExitInfo info = getExitInfo(raw.getPackageName(),
+ ApplicationExitInfo info = getExitInfoLocked(raw.getPackageName(),
raw.getPackageUid(), raw.getPid());
// query zygote and lmkd to get the exit info, and clear the saved info
@@ -312,7 +376,7 @@
raw.getPid(), raw.getRealUid());
Pair<Long, Object> lmkd = mAppExitInfoSourceLmkd.remove(
raw.getPid(), raw.getRealUid());
- mIsolatedUidRecords.removeIsolatedUid(raw.getRealUid());
+ mIsolatedUidRecords.removeIsolatedUidLocked(raw.getRealUid());
if (info == null) {
info = addExitInfoLocked(raw);
@@ -333,7 +397,7 @@
@VisibleForTesting
@GuardedBy("mLock")
void handleNoteAppKillLocked(final ApplicationExitInfo raw) {
- ApplicationExitInfo info = getExitInfo(
+ ApplicationExitInfo info = getExitInfoLocked(
raw.getPackageName(), raw.getPackageUid(), raw.getPid());
if (info == null) {
@@ -359,7 +423,7 @@
final String[] packages = raw.getPackageList();
final int uid = raw.getPackageUid();
for (int i = 0; i < packages.length; i++) {
- addExitInfoInner(packages[i], uid, info);
+ addExitInfoInnerLocked(packages[i], uid, info);
}
schedulePersistProcessExitInfo(false);
@@ -400,39 +464,37 @@
*
* @return true if a recond is updated
*/
- private boolean updateExitInfoIfNecessary(int pid, int uid, Integer status, Integer reason) {
- synchronized (mLock) {
- if (UserHandle.isIsolated(uid)) {
- Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid);
- if (k != null) {
- uid = k;
- }
- }
- ArrayList<ApplicationExitInfo> tlist = mTmpInfoList;
- tlist.clear();
- final int targetUid = uid;
- forEachPackage((packageName, records) -> {
- AppExitInfoContainer container = records.get(targetUid);
- if (container == null) {
- return FOREACH_ACTION_NONE;
- }
- tlist.clear();
- container.getExitInfoLocked(pid, 1, tlist);
- if (tlist.size() == 0) {
- return FOREACH_ACTION_NONE;
- }
- ApplicationExitInfo info = tlist.get(0);
- if (info.getRealUid() != targetUid) {
- tlist.clear();
- return FOREACH_ACTION_NONE;
- }
- // Okay found it, update its reason.
- updateExistingExitInfoRecordLocked(info, status, reason);
-
- return FOREACH_ACTION_STOP_ITERATION;
- });
- return tlist.size() > 0;
+ @GuardedBy("mLock")
+ private boolean updateExitInfoIfNecessaryLocked(
+ int pid, int uid, Integer status, Integer reason) {
+ Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid);
+ if (k != null) {
+ uid = k;
}
+ ArrayList<ApplicationExitInfo> tlist = mTmpInfoList;
+ tlist.clear();
+ final int targetUid = uid;
+ forEachPackageLocked((packageName, records) -> {
+ AppExitInfoContainer container = records.get(targetUid);
+ if (container == null) {
+ return FOREACH_ACTION_NONE;
+ }
+ tlist.clear();
+ container.getExitInfoLocked(pid, 1, tlist);
+ if (tlist.size() == 0) {
+ return FOREACH_ACTION_NONE;
+ }
+ ApplicationExitInfo info = tlist.get(0);
+ if (info.getRealUid() != targetUid) {
+ tlist.clear();
+ return FOREACH_ACTION_NONE;
+ }
+ // Okay found it, update its reason.
+ updateExistingExitInfoRecordLocked(info, status, reason);
+
+ return FOREACH_ACTION_STOP_ITERATION;
+ });
+ return tlist.size() > 0;
}
/**
@@ -441,38 +503,43 @@
@VisibleForTesting
void getExitInfo(final String packageName, final int filterUid,
final int filterPid, final int maxNum, final ArrayList<ApplicationExitInfo> results) {
- synchronized (mLock) {
- boolean emptyPackageName = TextUtils.isEmpty(packageName);
- if (!emptyPackageName) {
- // fast path
- AppExitInfoContainer container = mData.get(packageName, filterUid);
- if (container != null) {
- container.getExitInfoLocked(filterPid, maxNum, results);
- }
- } else {
- // slow path
- final ArrayList<ApplicationExitInfo> list = mTmpInfoList2;
- list.clear();
- // get all packages
- forEachPackage((name, records) -> {
- AppExitInfoContainer container = records.get(filterUid);
+ long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ boolean emptyPackageName = TextUtils.isEmpty(packageName);
+ if (!emptyPackageName) {
+ // fast path
+ AppExitInfoContainer container = mData.get(packageName, filterUid);
if (container != null) {
- mTmpInfoList.clear();
- results.addAll(container.toListLocked(mTmpInfoList, filterPid));
+ container.getExitInfoLocked(filterPid, maxNum, results);
}
- return AppExitInfoTracker.FOREACH_ACTION_NONE;
- });
+ } else {
+ // slow path
+ final ArrayList<ApplicationExitInfo> list = mTmpInfoList2;
+ list.clear();
+ // get all packages
+ forEachPackageLocked((name, records) -> {
+ AppExitInfoContainer container = records.get(filterUid);
+ if (container != null) {
+ mTmpInfoList.clear();
+ results.addAll(container.toListLocked(mTmpInfoList, filterPid));
+ }
+ return AppExitInfoTracker.FOREACH_ACTION_NONE;
+ });
- Collections.sort(list, (a, b) -> (int) (b.getTimestamp() - a.getTimestamp()));
- int size = list.size();
- if (maxNum > 0) {
- size = Math.min(size, maxNum);
+ Collections.sort(list, (a, b) -> (int) (b.getTimestamp() - a.getTimestamp()));
+ int size = list.size();
+ if (maxNum > 0) {
+ size = Math.min(size, maxNum);
+ }
+ for (int i = 0; i < size; i++) {
+ results.add(list.get(i));
+ }
+ list.clear();
}
- for (int i = 0; i < size; i++) {
- results.add(list.get(i));
- }
- list.clear();
}
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
}
@@ -480,17 +547,16 @@
* Return the first matching exit info record, for internal use, the parameters are not supposed
* to be empty.
*/
- private ApplicationExitInfo getExitInfo(final String packageName,
+ @GuardedBy("mLock")
+ private ApplicationExitInfo getExitInfoLocked(final String packageName,
final int filterUid, final int filterPid) {
- synchronized (mLock) {
- ArrayList<ApplicationExitInfo> list = mTmpInfoList;
- list.clear();
- getExitInfo(packageName, filterUid, filterPid, 1, list);
+ ArrayList<ApplicationExitInfo> list = mTmpInfoList;
+ list.clear();
+ getExitInfo(packageName, filterUid, filterPid, 1, list);
- ApplicationExitInfo info = list.size() > 0 ? list.get(0) : null;
- list.clear();
- return info;
- }
+ ApplicationExitInfo info = list.size() > 0 ? list.get(0) : null;
+ list.clear();
+ return info;
}
@VisibleForTesting
@@ -498,8 +564,10 @@
mAppExitInfoSourceZygote.removeByUserId(userId);
mAppExitInfoSourceLmkd.removeByUserId(userId);
mIsolatedUidRecords.removeByUserId(userId);
- removeByUserId(userId);
- schedulePersistProcessExitInfo(true);
+ synchronized (mLock) {
+ removeByUserIdLocked(userId);
+ schedulePersistProcessExitInfo(true);
+ }
}
@VisibleForTesting
@@ -507,13 +575,16 @@
if (packageName != null) {
final boolean removeUid = TextUtils.isEmpty(
mService.mPackageManagerInt.getNameForUid(uid));
- if (removeUid) {
- mAppExitInfoSourceZygote.removeByUid(uid, allUsers);
- mAppExitInfoSourceLmkd.removeByUid(uid, allUsers);
- mIsolatedUidRecords.removeAppUid(uid, allUsers);
+ synchronized (mLock) {
+ if (removeUid) {
+ mAppExitInfoSourceZygote.removeByUidLocked(uid, allUsers);
+ mAppExitInfoSourceLmkd.removeByUidLocked(uid, allUsers);
+ mIsolatedUidRecords.removeAppUid(uid, allUsers);
+ }
+ removePackageLocked(packageName, uid, removeUid,
+ allUsers ? UserHandle.USER_ALL : UserHandle.getUserId(uid));
+ schedulePersistProcessExitInfo(true);
}
- removePackage(packageName, allUsers ? UserHandle.USER_ALL : UserHandle.getUserId(uid));
- schedulePersistProcessExitInfo(true);
}
}
@@ -593,6 +664,7 @@
}
}
synchronized (mLock) {
+ pruneAnrTracesIfNecessaryLocked();
mAppExitInfoLoaded = true;
}
}
@@ -634,7 +706,7 @@
ProtoOutputStream proto = new ProtoOutputStream(out);
proto.write(AppsExitInfoProto.LAST_UPDATE_TIMESTAMP, now);
synchronized (mLock) {
- forEachPackage((packageName, records) -> {
+ forEachPackageLocked((packageName, records) -> {
long token = proto.start(AppsExitInfoProto.PACKAGES);
proto.write(AppsExitInfoProto.Package.PACKAGE_NAME, packageName);
int uidArraySize = records.size();
@@ -688,6 +760,9 @@
mProcExitInfoFile.delete();
}
mData.getMap().clear();
+ mActiveAppStateSummary.clear();
+ mActiveAppTraces.clear();
+ pruneAnrTracesIfNecessaryLocked();
}
}
@@ -695,15 +770,15 @@
* Helper function for shell command
*/
void clearHistoryProcessExitInfo(String packageName, int userId) {
- synchronized (mLock) {
- if (TextUtils.isEmpty(packageName)) {
- if (userId == UserHandle.USER_ALL) {
- mData.getMap().clear();
- } else {
- removeByUserId(userId);
- }
- } else {
- removePackage(packageName, userId);
+ if (TextUtils.isEmpty(packageName)) {
+ synchronized (mLock) {
+ removeByUserIdLocked(userId);
+ }
+ } else {
+ final int uid = mService.mPackageManagerInt.getPackageUid(packageName,
+ PackageManager.MATCH_ALL, userId);
+ synchronized (mLock) {
+ removePackageLocked(packageName, uid, true, userId);
}
}
schedulePersistProcessExitInfo(true);
@@ -716,7 +791,7 @@
pw.println("Last Timestamp of Persistence Into Persistent Storage: "
+ sdf.format(new Date(mLastAppExitInfoPersistTimestamp)));
if (TextUtils.isEmpty(packageName)) {
- forEachPackage((name, records) -> {
+ forEachPackageLocked((name, records) -> {
dumpHistoryProcessExitInfoLocked(pw, " ", name, records, sdf);
return AppExitInfoTracker.FOREACH_ACTION_NONE;
});
@@ -741,86 +816,108 @@
}
}
- private void addExitInfoInner(String packageName, int userId, ApplicationExitInfo info) {
- synchronized (mLock) {
- AppExitInfoContainer container = mData.get(packageName, userId);
- if (container == null) {
- container = new AppExitInfoContainer(mAppExitInfoHistoryListSize);
- if (UserHandle.isIsolated(info.getRealUid())) {
- Integer k = mIsolatedUidRecords.getUidByIsolatedUid(info.getRealUid());
- if (k != null) {
- container.mUid = k;
- }
- } else {
- container.mUid = info.getRealUid();
+ @GuardedBy("mLock")
+ private void addExitInfoInnerLocked(String packageName, int userId, ApplicationExitInfo info) {
+ AppExitInfoContainer container = mData.get(packageName, userId);
+ if (container == null) {
+ container = new AppExitInfoContainer(mAppExitInfoHistoryListSize);
+ if (UserHandle.isIsolated(info.getRealUid())) {
+ Integer k = mIsolatedUidRecords.getUidByIsolatedUid(info.getRealUid());
+ if (k != null) {
+ container.mUid = k;
}
- mData.put(packageName, userId, container);
+ } else {
+ container.mUid = info.getRealUid();
}
- container.addExitInfoLocked(info);
+ mData.put(packageName, userId, container);
}
+ container.addExitInfoLocked(info);
}
- private void forEachPackage(
+ @GuardedBy("mLocked")
+ private void forEachPackageLocked(
BiFunction<String, SparseArray<AppExitInfoContainer>, Integer> callback) {
if (callback != null) {
- synchronized (mLock) {
- ArrayMap<String, SparseArray<AppExitInfoContainer>> map = mData.getMap();
- for (int i = map.size() - 1; i >= 0; i--) {
- switch (callback.apply(map.keyAt(i), map.valueAt(i))) {
- case FOREACH_ACTION_REMOVE_PACKAGE:
- map.removeAt(i);
- break;
- case FOREACH_ACTION_STOP_ITERATION:
- i = 0;
- break;
- case FOREACH_ACTION_NONE:
- default:
- break;
- }
- }
- }
- }
- }
-
- private void removePackage(String packageName, int userId) {
- synchronized (mLock) {
- if (userId == UserHandle.USER_ALL) {
- mData.getMap().remove(packageName);
- } else {
- ArrayMap<String, SparseArray<AppExitInfoContainer>> map =
- mData.getMap();
- SparseArray<AppExitInfoContainer> array = map.get(packageName);
- if (array == null) {
- return;
- }
- for (int i = array.size() - 1; i >= 0; i--) {
- if (UserHandle.getUserId(array.keyAt(i)) == userId) {
- array.removeAt(i);
+ ArrayMap<String, SparseArray<AppExitInfoContainer>> map = mData.getMap();
+ for (int i = map.size() - 1; i >= 0; i--) {
+ switch (callback.apply(map.keyAt(i), map.valueAt(i))) {
+ case FOREACH_ACTION_REMOVE_ITEM:
+ final SparseArray<AppExitInfoContainer> records = map.valueAt(i);
+ for (int j = records.size() - 1; j >= 0; j--) {
+ records.valueAt(j).destroyLocked();
+ }
+ map.removeAt(i);
break;
- }
- }
- if (array.size() == 0) {
- map.remove(packageName);
+ case FOREACH_ACTION_STOP_ITERATION:
+ i = 0;
+ break;
+ case FOREACH_ACTION_NONE:
+ default:
+ break;
}
}
}
}
- private void removeByUserId(final int userId) {
- if (userId == UserHandle.USER_ALL) {
- synchronized (mLock) {
- mData.getMap().clear();
+ @GuardedBy("mLocked")
+ private void removePackageLocked(String packageName, int uid, boolean removeUid, int userId) {
+ if (removeUid) {
+ mActiveAppStateSummary.remove(uid);
+ final int idx = mActiveAppTraces.indexOfKey(uid);
+ if (idx >= 0) {
+ final SparseArray<File> array = mActiveAppTraces.valueAt(idx);
+ for (int i = array.size() - 1; i >= 0; i--) {
+ array.valueAt(i).delete();
+ }
+ mActiveAppTraces.removeAt(idx);
}
+ }
+ ArrayMap<String, SparseArray<AppExitInfoContainer>> map = mData.getMap();
+ SparseArray<AppExitInfoContainer> array = map.get(packageName);
+ if (array == null) {
return;
}
- forEachPackage((packageName, records) -> {
+ if (userId == UserHandle.USER_ALL) {
+ for (int i = array.size() - 1; i >= 0; i--) {
+ array.valueAt(i).destroyLocked();
+ }
+ mData.getMap().remove(packageName);
+ } else {
+ for (int i = array.size() - 1; i >= 0; i--) {
+ if (UserHandle.getUserId(array.keyAt(i)) == userId) {
+ array.valueAt(i).destroyLocked();
+ array.removeAt(i);
+ break;
+ }
+ }
+ if (array.size() == 0) {
+ map.remove(packageName);
+ }
+ }
+ }
+
+ @GuardedBy("mLocked")
+ private void removeByUserIdLocked(final int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ mData.getMap().clear();
+ mActiveAppStateSummary.clear();
+ mActiveAppTraces.clear();
+ pruneAnrTracesIfNecessaryLocked();
+ return;
+ }
+ removeFromSparse2dArray(mActiveAppStateSummary,
+ (v) -> UserHandle.getUserId(v) == userId, null, null);
+ removeFromSparse2dArray(mActiveAppTraces,
+ (v) -> UserHandle.getUserId(v) == userId, null, (v) -> v.delete());
+ forEachPackageLocked((packageName, records) -> {
for (int i = records.size() - 1; i >= 0; i--) {
if (UserHandle.getUserId(records.keyAt(i)) == userId) {
+ records.valueAt(i).destroyLocked();
records.removeAt(i);
break;
}
}
- return records.size() == 0 ? FOREACH_ACTION_REMOVE_PACKAGE : FOREACH_ACTION_NONE;
+ return records.size() == 0 ? FOREACH_ACTION_REMOVE_ITEM : FOREACH_ACTION_NONE;
});
}
@@ -862,6 +959,262 @@
}
/**
+ * Called from {@link ActivityManagerService#setProcessStateSummary}.
+ */
+ @VisibleForTesting
+ void setProcessStateSummary(int uid, final int pid, final byte[] data) {
+ synchronized (mLock) {
+ Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid);
+ if (k != null) {
+ uid = k;
+ }
+ putToSparse2dArray(mActiveAppStateSummary, uid, pid, data, SparseArray::new, null);
+ }
+ }
+
+ @VisibleForTesting
+ @Nullable byte[] getProcessStateSummary(int uid, final int pid) {
+ synchronized (mLock) {
+ Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid);
+ if (k != null) {
+ uid = k;
+ }
+ int index = mActiveAppStateSummary.indexOfKey(uid);
+ if (index < 0) {
+ return null;
+ }
+ return mActiveAppStateSummary.valueAt(index).get(pid);
+ }
+ }
+
+ /**
+ * Called from ProcessRecord when an ANR occurred and the ANR trace is taken.
+ */
+ void scheduleLogAnrTrace(final int pid, final int uid, final String[] packageList,
+ final File traceFile, final long startOff, final long endOff) {
+ mKillHandler.sendMessage(PooledLambda.obtainMessage(
+ this::handleLogAnrTrace, pid, uid, packageList,
+ traceFile, startOff, endOff));
+ }
+
+ /**
+ * Copy and compress the given ANR trace file
+ */
+ @VisibleForTesting
+ void handleLogAnrTrace(final int pid, int uid, final String[] packageList,
+ final File traceFile, final long startOff, final long endOff) {
+ if (!traceFile.exists() || ArrayUtils.isEmpty(packageList)) {
+ return;
+ }
+ final long size = traceFile.length();
+ final long length = endOff - startOff;
+ if (startOff >= size || endOff > size || length <= 0) {
+ return;
+ }
+
+ final File outFile = new File(mProcExitStoreDir, traceFile.getName()
+ + APP_TRACE_FILE_SUFFIX);
+ // Copy & compress
+ if (copyToGzFile(traceFile, outFile, startOff, length)) {
+ // Wrote successfully.
+ synchronized (mLock) {
+ Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid);
+ if (k != null) {
+ uid = k;
+ }
+ if (DEBUG_PROCESSES) {
+ Slog.i(TAG, "Stored ANR traces of " + pid + "/u" + uid + " in " + outFile);
+ }
+ boolean pending = true;
+ // Unlikely but possible: the app has died
+ for (int i = 0; i < packageList.length; i++) {
+ final AppExitInfoContainer container = mData.get(packageList[i], uid);
+ // Try to see if we could append this trace to an existing record
+ if (container != null && container.appendTraceIfNecessaryLocked(pid, outFile)) {
+ // Okay someone took it
+ pending = false;
+ }
+ }
+ if (pending) {
+ // Save it into a temporary list for later use (when the app dies).
+ putToSparse2dArray(mActiveAppTraces, uid, pid, outFile,
+ SparseArray::new, (v) -> v.delete());
+ }
+ }
+ }
+ }
+
+ /**
+ * Copy the given portion of the file into a gz file.
+ *
+ * @param inFile The source file.
+ * @param outFile The destination file, which will be compressed in gzip format.
+ * @param start The start offset where the copy should start from.
+ * @param length The number of bytes that should be copied.
+ * @return If the copy was successful or not.
+ */
+ private static boolean copyToGzFile(final File inFile, final File outFile,
+ final long start, final long length) {
+ long remaining = length;
+ try (
+ BufferedInputStream in = new BufferedInputStream(new FileInputStream(inFile));
+ GZIPOutputStream out = new GZIPOutputStream(new BufferedOutputStream(
+ new FileOutputStream(outFile)))) {
+ final byte[] buffer = new byte[8192];
+ in.skip(start);
+ while (remaining > 0) {
+ int t = in.read(buffer, 0, (int) Math.min(buffer.length, remaining));
+ if (t < 0) {
+ break;
+ }
+ out.write(buffer, 0, t);
+ remaining -= t;
+ }
+ } catch (IOException e) {
+ if (DEBUG_PROCESSES) {
+ Slog.e(TAG, "Error in copying ANR trace from " + inFile + " to " + outFile, e);
+ }
+ return false;
+ }
+ return remaining == 0 && outFile.exists();
+ }
+
+ /**
+ * In case there is any orphan ANR trace file, remove it.
+ */
+ @GuardedBy("mLock")
+ private void pruneAnrTracesIfNecessaryLocked() {
+ final ArraySet<String> allFiles = new ArraySet();
+ final File[] files = mProcExitStoreDir.listFiles((f) -> {
+ final String name = f.getName();
+ boolean trace = name.startsWith(ActivityManagerService.ANR_FILE_PREFIX)
+ && name.endsWith(APP_TRACE_FILE_SUFFIX);
+ if (trace) {
+ allFiles.add(name);
+ }
+ return trace;
+ });
+ if (ArrayUtils.isEmpty(files)) {
+ return;
+ }
+ // Find out the owners from the existing records
+ forEachPackageLocked((name, records) -> {
+ for (int i = records.size() - 1; i >= 0; i--) {
+ final AppExitInfoContainer container = records.valueAt(i);
+ container.forEachRecordLocked((pid, info) -> {
+ final File traceFile = info.getTraceFile();
+ if (traceFile != null) {
+ allFiles.remove(traceFile.getName());
+ }
+ return FOREACH_ACTION_NONE;
+ });
+ }
+ return AppExitInfoTracker.FOREACH_ACTION_NONE;
+ });
+ // See if there is any active process owns it.
+ forEachSparse2dArray(mActiveAppTraces, (v) -> allFiles.remove(v.getName()));
+
+ // Remove orphan traces if nobody claims it.
+ for (int i = allFiles.size() - 1; i >= 0; i--) {
+ (new File(mProcExitStoreDir, allFiles.valueAt(i))).delete();
+ }
+ }
+
+ /**
+ * A utility function to add the given value to the given 2d SparseArray
+ */
+ private static <T extends SparseArray<U>, U> void putToSparse2dArray(final SparseArray<T> array,
+ final int outerKey, final int innerKey, final U value, final Supplier<T> newInstance,
+ final Consumer<U> actionToOldValue) {
+ int idx = array.indexOfKey(outerKey);
+ T innerArray = null;
+ if (idx < 0) {
+ innerArray = newInstance.get();
+ array.put(outerKey, innerArray);
+ } else {
+ innerArray = array.valueAt(idx);
+ }
+ idx = innerArray.indexOfKey(innerKey);
+ if (idx >= 0) {
+ if (actionToOldValue != null) {
+ actionToOldValue.accept(innerArray.valueAt(idx));
+ }
+ innerArray.setValueAt(idx, value);
+ } else {
+ innerArray.put(innerKey, value);
+ }
+ }
+
+ /**
+ * A utility function to iterate through the given 2d SparseArray
+ */
+ private static <T extends SparseArray<U>, U> void forEachSparse2dArray(
+ final SparseArray<T> array, final Consumer<U> action) {
+ if (action != null) {
+ for (int i = array.size() - 1; i >= 0; i--) {
+ T innerArray = array.valueAt(i);
+ if (innerArray == null) {
+ continue;
+ }
+ for (int j = innerArray.size() - 1; j >= 0; j--) {
+ action.accept(innerArray.valueAt(j));
+ }
+ }
+ }
+ }
+
+ /**
+ * A utility function to remove elements from the given 2d SparseArray
+ */
+ private static <T extends SparseArray<U>, U> void removeFromSparse2dArray(
+ final SparseArray<T> array, final Predicate<Integer> outerPredicate,
+ final Predicate<Integer> innerPredicate, final Consumer<U> action) {
+ for (int i = array.size() - 1; i >= 0; i--) {
+ if (outerPredicate == null || outerPredicate.test(array.keyAt(i))) {
+ final T innerArray = array.valueAt(i);
+ if (innerArray == null) {
+ continue;
+ }
+ for (int j = innerArray.size() - 1; j >= 0; j--) {
+ if (innerPredicate == null || innerPredicate.test(innerArray.keyAt(j))) {
+ if (action != null) {
+ action.accept(innerArray.valueAt(j));
+ }
+ innerArray.removeAt(j);
+ }
+ }
+ if (innerArray.size() == 0) {
+ array.removeAt(i);
+ }
+ }
+ }
+ }
+
+ /**
+ * A utility function to find and remove elements from the given 2d SparseArray.
+ */
+ private static <T extends SparseArray<U>, U> U findAndRemoveFromSparse2dArray(
+ final SparseArray<T> array, final int outerKey, final int innerKey) {
+ final int idx = array.indexOfKey(outerKey);
+ if (idx >= 0) {
+ T p = array.valueAt(idx);
+ if (p == null) {
+ return null;
+ }
+ final int innerIdx = p.indexOfKey(innerKey);
+ if (innerIdx >= 0) {
+ final U ret = p.valueAt(innerIdx);
+ p.removeAt(innerIdx);
+ if (p.size() == 0) {
+ array.removeAt(idx);
+ }
+ return ret;
+ }
+ }
+ return null;
+ }
+
+ /**
* A container class of {@link android.app.ApplicationExitInfo}
*/
final class AppExitInfoContainer {
@@ -934,10 +1287,68 @@
}
}
if (oldestIndex >= 0) {
+ final File traceFile = mInfos.valueAt(oldestIndex).getTraceFile();
+ if (traceFile != null) {
+ traceFile.delete();
+ }
mInfos.removeAt(oldestIndex);
}
}
- mInfos.append(info.getPid(), info);
+ // Claim the state information if there is any
+ final int uid = info.getPackageUid();
+ final int pid = info.getPid();
+ info.setProcessStateSummary(findAndRemoveFromSparse2dArray(
+ mActiveAppStateSummary, uid, pid));
+ info.setTraceFile(findAndRemoveFromSparse2dArray(mActiveAppTraces, uid, pid));
+ info.setAppTraceRetriever(mAppTraceRetriever);
+ mInfos.append(pid, info);
+ }
+
+ @GuardedBy("mLock")
+ boolean appendTraceIfNecessaryLocked(final int pid, final File traceFile) {
+ final ApplicationExitInfo r = mInfos.get(pid);
+ if (r != null) {
+ r.setTraceFile(traceFile);
+ r.setAppTraceRetriever(mAppTraceRetriever);
+ return true;
+ }
+ return false;
+ }
+
+ @GuardedBy("mLock")
+ void destroyLocked() {
+ for (int i = mInfos.size() - 1; i >= 0; i--) {
+ ApplicationExitInfo ai = mInfos.valueAt(i);
+ final File traceFile = ai.getTraceFile();
+ if (traceFile != null) {
+ traceFile.delete();
+ }
+ ai.setTraceFile(null);
+ ai.setAppTraceRetriever(null);
+ }
+ }
+
+ @GuardedBy("mLock")
+ void forEachRecordLocked(final BiFunction<Integer, ApplicationExitInfo, Integer> callback) {
+ if (callback != null) {
+ for (int i = mInfos.size() - 1; i >= 0; i--) {
+ switch (callback.apply(mInfos.keyAt(i), mInfos.valueAt(i))) {
+ case FOREACH_ACTION_REMOVE_ITEM:
+ final File traceFile = mInfos.valueAt(i).getTraceFile();
+ if (traceFile != null) {
+ traceFile.delete();
+ }
+ mInfos.removeAt(i);
+ break;
+ case FOREACH_ACTION_STOP_ITERATION:
+ i = 0;
+ break;
+ case FOREACH_ACTION_NONE:
+ default:
+ break;
+ }
+ }
+ }
}
@GuardedBy("mLock")
@@ -1033,6 +1444,7 @@
}
}
+ @GuardedBy("mLock")
Integer getUidByIsolatedUid(int isolatedUid) {
if (UserHandle.isIsolated(isolatedUid)) {
synchronized (mLock) {
@@ -1053,6 +1465,7 @@
}
}
+ @VisibleForTesting
void removeAppUid(int uid, boolean allUsers) {
synchronized (mLock) {
if (allUsers) {
@@ -1071,23 +1484,22 @@
}
}
- int removeIsolatedUid(int isolatedUid) {
+ @GuardedBy("mLock")
+ int removeIsolatedUidLocked(int isolatedUid) {
if (!UserHandle.isIsolated(isolatedUid)) {
return isolatedUid;
}
- synchronized (mLock) {
- int uid = mIsolatedUidToUidMap.get(isolatedUid, -1);
- if (uid == -1) {
- return isolatedUid;
- }
- mIsolatedUidToUidMap.remove(isolatedUid);
- ArraySet<Integer> set = mUidToIsolatedUidMap.get(uid);
- if (set != null) {
- set.remove(isolatedUid);
- }
- // let the ArraySet stay in the mUidToIsolatedUidMap even if it's empty
- return uid;
+ int uid = mIsolatedUidToUidMap.get(isolatedUid, -1);
+ if (uid == -1) {
+ return isolatedUid;
}
+ mIsolatedUidToUidMap.remove(isolatedUid);
+ ArraySet<Integer> set = mUidToIsolatedUidMap.get(uid);
+ if (set != null) {
+ set.remove(isolatedUid);
+ }
+ // let the ArraySet stay in the mUidToIsolatedUidMap even if it's empty
+ return uid;
}
void removeByUserId(int userId) {
@@ -1193,33 +1605,29 @@
mPresetReason = reason;
}
- void add(int pid, int uid, Object extra) {
- if (UserHandle.isIsolated(uid)) {
- Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid);
- if (k != null) {
- uid = k;
- }
+ @GuardedBy("mLock")
+ private void addLocked(int pid, int uid, Object extra) {
+ Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid);
+ if (k != null) {
+ uid = k;
}
- synchronized (mLock) {
- SparseArray<Pair<Long, Object>> array = mData.get(uid);
- if (array == null) {
- array = new SparseArray<Pair<Long, Object>>();
- mData.put(uid, array);
- }
- array.put(pid, new Pair<Long, Object>(System.currentTimeMillis(), extra));
+ SparseArray<Pair<Long, Object>> array = mData.get(uid);
+ if (array == null) {
+ array = new SparseArray<Pair<Long, Object>>();
+ mData.put(uid, array);
}
+ array.put(pid, new Pair<Long, Object>(System.currentTimeMillis(), extra));
}
+ @VisibleForTesting
Pair<Long, Object> remove(int pid, int uid) {
- if (UserHandle.isIsolated(uid)) {
+ synchronized (mLock) {
Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid);
if (k != null) {
uid = k;
}
- }
- synchronized (mLock) {
SparseArray<Pair<Long, Object>> array = mData.get(uid);
if (array != null) {
Pair<Long, Object> p = array.get(pid);
@@ -1228,8 +1636,8 @@
return isFresh(p.first) ? p : null;
}
}
+ return null;
}
- return null;
}
void removeByUserId(int userId) {
@@ -1250,7 +1658,8 @@
}
}
- void removeByUid(int uid, boolean allUsers) {
+ @GuardedBy("mLock")
+ void removeByUidLocked(int uid, boolean allUsers) {
if (UserHandle.isIsolated(uid)) {
Integer k = mIsolatedUidRecords.getUidByIsolatedUid(uid);
if (k != null) {
@@ -1260,17 +1669,13 @@
if (allUsers) {
uid = UserHandle.getAppId(uid);
- synchronized (mLock) {
- for (int i = mData.size() - 1; i >= 0; i--) {
- if (UserHandle.getAppId(mData.keyAt(i)) == uid) {
- mData.removeAt(i);
- }
+ for (int i = mData.size() - 1; i >= 0; i--) {
+ if (UserHandle.getAppId(mData.keyAt(i)) == uid) {
+ mData.removeAt(i);
}
}
} else {
- synchronized (mLock) {
- mData.remove(uid);
- }
+ mData.remove(uid);
}
}
@@ -1292,12 +1697,12 @@
// Unlikely but possible: the record has been created
// Let's update it if we could find a ApplicationExitInfo record
- if (!updateExitInfoIfNecessary(pid, uid, status, mPresetReason)) {
- add(pid, uid, status);
- }
-
- // Notify any interesed party regarding the lmkd kills
synchronized (mLock) {
+ if (!updateExitInfoIfNecessaryLocked(pid, uid, status, mPresetReason)) {
+ addLocked(pid, uid, status);
+ }
+
+ // Notify any interesed party regarding the lmkd kills
final BiConsumer<Integer, Integer> listener = mProcDiedListener;
if (listener != null) {
mService.mHandler.post(()-> listener.accept(pid, uid));
@@ -1305,4 +1710,51 @@
}
}
}
+
+ /**
+ * The implementation to the IAppTraceRetriever interface.
+ */
+ @VisibleForTesting
+ class AppTraceRetriever extends IAppTraceRetriever.Stub {
+ @Override
+ public ParcelFileDescriptor getTraceFileDescriptor(final String packageName,
+ final int uid, final int pid) {
+ mService.enforceNotIsolatedCaller("getTraceFileDescriptor");
+
+ if (TextUtils.isEmpty(packageName)) {
+ throw new IllegalArgumentException("Invalid package name");
+ }
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getCallingUserId();
+ final int userId = UserHandle.getUserId(uid);
+
+ mService.mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
+ ALLOW_NON_FULL, "getTraceFileDescriptor", null);
+ if (mService.enforceDumpPermissionForPackage(packageName, userId,
+ callingUid, "getTraceFileDescriptor") != Process.INVALID_UID) {
+ synchronized (mLock) {
+ final ApplicationExitInfo info = getExitInfoLocked(packageName, uid, pid);
+ if (info == null) {
+ return null;
+ }
+ final File traceFile = info.getTraceFile();
+ if (traceFile == null) {
+ return null;
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ // The fd will be closed after being written into Parcel
+ return ParcelFileDescriptor.open(traceFile,
+ ParcelFileDescriptor.MODE_READ_ONLY);
+ } catch (FileNotFoundException e) {
+ return null;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+ return null;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/BugReportHandlerUtil.java b/services/core/java/com/android/server/am/BugReportHandlerUtil.java
index ba89fce..03f4a54 100644
--- a/services/core/java/com/android/server/am/BugReportHandlerUtil.java
+++ b/services/core/java/com/android/server/am/BugReportHandlerUtil.java
@@ -16,15 +16,20 @@
package com.android.server.am;
+import static android.app.AppOpsManager.OP_NONE;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import android.app.Activity;
import android.app.BroadcastOptions;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Binder;
+import android.os.BugreportManager;
+import android.os.BugreportParams;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -110,9 +115,17 @@
options.setBackgroundActivityStartsAllowed(true);
final long identity = Binder.clearCallingIdentity();
try {
- context.sendBroadcastAsUser(intent, UserHandle.of(handlerUser),
+ // Handler app's BroadcastReceiver should call setResultCode(Activity.RESULT_OK) to
+ // let ResultBroadcastReceiver know the handler app is available.
+ context.sendOrderedBroadcastAsUser(intent,
+ UserHandle.of(handlerUser),
android.Manifest.permission.DUMP,
- options.toBundle());
+ OP_NONE, options.toBundle(),
+ new ResultBroadcastReceiver(),
+ /* scheduler= */ null,
+ Activity.RESULT_CANCELED,
+ /* initialData= */ null,
+ /* initialExtras= */ null);
} catch (RuntimeException e) {
Slog.e(TAG, "Error while trying to launch bugreport handler app.", e);
return false;
@@ -176,4 +189,19 @@
Binder.restoreCallingIdentity(identity);
}
}
+
+ private static class ResultBroadcastReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (getResultCode() == Activity.RESULT_OK) {
+ return;
+ }
+
+ Slog.w(TAG, "Request bug report because handler app seems to be not available.");
+ BugreportManager bugreportManager = context.getSystemService(BugreportManager.class);
+ bugreportManager.requestBugreport(
+ new BugreportParams(BugreportParams.BUGREPORT_MODE_INTERACTIVE),
+ /* shareTitle= */null, /* shareDescription= */ null);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 57bd42b..0f9d61f 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -71,7 +71,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManagerInternal;
-import android.content.pm.ProcessInfo;
import android.content.res.Resources;
import android.graphics.Point;
import android.net.LocalSocket;
@@ -99,7 +98,6 @@
import android.system.Os;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.ArraySet;
import android.util.EventLog;
import android.util.LongSparseArray;
import android.util.Pair;
@@ -138,10 +136,8 @@
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Set;
/**
* Activity manager code dealing with processes.
@@ -512,13 +508,6 @@
*/
private final int[] mZygoteSigChldMessage = new int[3];
- interface LmkdKillListener {
- /**
- * Called when there is a process kill by lmkd.
- */
- void onLmkdKillOccurred(int pid, int uid);
- }
-
final class IsolatedUidRange {
@VisibleForTesting
public final int mFirstUid;
@@ -2192,11 +2181,12 @@
app.setHasForegroundActivities(true);
}
+ StorageManagerInternal storageManagerInternal = LocalServices.getService(
+ StorageManagerInternal.class);
final Map<String, Pair<String, Long>> pkgDataInfoMap;
boolean bindMountAppStorageDirs = false;
if (shouldIsolateAppData(app)) {
- bindMountAppStorageDirs = mVoldAppDataIsolationEnabled;
// Get all packages belongs to the same shared uid. sharedPackages is empty array
// if it doesn't have shared uid.
final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked();
@@ -2206,9 +2196,9 @@
? new String[]{app.info.packageName} : sharedPackages, uid);
int userId = UserHandle.getUserId(uid);
- if (mVoldAppDataIsolationEnabled) {
- StorageManagerInternal storageManagerInternal = LocalServices.getService(
- StorageManagerInternal.class);
+ if (mVoldAppDataIsolationEnabled && UserHandle.isApp(app.uid) &&
+ !storageManagerInternal.isExternalStorageService(uid)) {
+ bindMountAppStorageDirs = true;
if (!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
app.processName)) {
// Cannot prepare Android/app and Android/obb directory,
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index e7f66bb..eec7519 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1621,9 +1621,11 @@
// For background ANRs, don't pass the ProcessCpuTracker to
// avoid spending 1/2 second collecting stats to rank lastPids.
StringWriter tracesFileException = new StringWriter();
+ // To hold the start and end offset to the ANR trace file respectively.
+ final long[] offsets = new long[2];
File tracesFile = ActivityManagerService.dumpStackTraces(firstPids,
(isSilentAnr()) ? null : processCpuTracker, (isSilentAnr()) ? null : lastPids,
- nativePids, tracesFileException);
+ nativePids, tracesFileException, offsets);
if (isMonitorCpuUsage()) {
mService.updateCpuStatsNow();
@@ -1641,6 +1643,10 @@
if (tracesFile == null) {
// There is no trace file, so dump (only) the alleged culprit's threads to the log
Process.sendSignal(pid, Process.SIGNAL_QUIT);
+ } else if (offsets[1] > 0) {
+ // We've dumped into the trace file successfully
+ mService.mProcessList.mAppExitInfoTracker.scheduleLogAnrTrace(
+ pid, uid, getPackageList(), tracesFile, offsets[0], offsets[1]);
}
FrameworkStatsLog.write(FrameworkStatsLog.ANR_OCCURRED, uid, processName,
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index a7125b4..343b4ba 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -2218,19 +2218,23 @@
/**
* Returns whether the given user requires credential entry at this time. This is used to
- * intercept activity launches for work apps when the Work Challenge is present.
+ * intercept activity launches for locked work apps due to work challenge being triggered
+ * or when the profile user is yet to be unlocked.
*/
protected boolean shouldConfirmCredentials(@UserIdInt int userId) {
- synchronized (mLock) {
- if (mStartedUsers.get(userId) == null) {
- return false;
- }
- }
- if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
+ if (getStartedUserState(userId) == null) {
return false;
}
- final KeyguardManager km = mInjector.getKeyguardManager();
- return km.isDeviceLocked(userId) && km.isDeviceSecure(userId);
+ if (!getUserInfo(userId).isManagedProfile()) {
+ return false;
+ }
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
+ final KeyguardManager km = mInjector.getKeyguardManager();
+ return km.isDeviceLocked(userId) && km.isDeviceSecure(userId);
+ } else {
+ // For unified challenge, need to confirm credential if user is RUNNING_LOCKED.
+ return isUserRunning(userId, ActivityManager.FLAG_AND_LOCKED);
+ }
}
boolean isLockScreenDisabled(@UserIdInt int userId) {
diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index 04c792a..d548871 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -25,6 +25,7 @@
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
+import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -220,7 +221,7 @@
mNetworkTemplate = new NetworkTemplate(
NetworkTemplate.MATCH_MOBILE, subscriberId, new String[] { subscriberId },
null, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
- NetworkStats.DEFAULT_NETWORK_NO);
+ NetworkStats.DEFAULT_NETWORK_NO, NETWORK_TYPE_ALL);
mUsageCallback = new UsageCallback() {
@Override
public void onThresholdReached(int networkType, String subscriberId) {
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index c1c3760..1b4ec8a 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -530,6 +530,11 @@
return Settings.Global.getInt(contentResolver, keyName, defaultValue);
}
+ public int settingsSecureGetInt(ContentResolver contentResolver, String keyName,
+ int defaultValue, int userId) {
+ return Settings.Secure.getIntForUser(contentResolver, keyName, defaultValue, userId);
+ }
+
public @NonNull ManagedProfilePasswordCache getManagedProfilePasswordCache() {
try {
java.security.KeyStore ks = java.security.KeyStore.getInstance("AndroidKeyStore");
@@ -1010,6 +1015,13 @@
}
}
+ private void enforceFrpResolved() {
+ if (mInjector.settingsSecureGetInt(mContext.getContentResolver(),
+ Settings.Secure.SECURE_FRP_MODE, 0, UserHandle.USER_SYSTEM) == 1) {
+ throw new SecurityException("Cannot change credential while FRP is not resolved yet");
+ }
+ }
+
private final void checkWritePermission(int userId) {
mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite");
}
@@ -1572,6 +1584,7 @@
"This operation requires secure lock screen feature");
}
checkWritePermission(userId);
+ enforceFrpResolved();
// When changing credential for profiles with unified challenge, some callers
// will pass in empty credential while others will pass in the credential of
diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
index 265b9ad..28f8380 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
@@ -85,7 +85,9 @@
mListener = listener;
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
buildBluetoothRoutes();
+ }
+ public void start() {
mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP);
mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEARING_AID);
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 5c97e90..c7d14e0 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -103,25 +103,20 @@
publishProviderState();
boolean sessionInfoChanged;
- synchronized (mLock) {
- sessionInfoChanged = updateSessionInfosIfNeededLocked();
- }
+ sessionInfoChanged = updateSessionInfosIfNeeded();
if (sessionInfoChanged) {
notifySessionInfoUpdated();
}
});
-
- mHandler.post(() -> notifyProviderState());
-
- //TODO: clean up this
- // This is required because it is not instantiated in the main thread and
- // BluetoothRoutesUpdatedListener can be called before here
- synchronized (mLock) {
- updateSessionInfosIfNeededLocked();
- }
+ updateSessionInfosIfNeeded();
mContext.registerReceiver(new VolumeChangeReceiver(),
new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION));
+
+ mHandler.post(() -> {
+ mBtRouteProvider.start();
+ notifyProviderState();
+ });
}
@Override
@@ -220,35 +215,38 @@
/**
* Updates the mSessionInfo. Returns true if the session info is changed.
*/
- boolean updateSessionInfosIfNeededLocked() {
- // Prevent to execute this method before mBtRouteProvider is created.
- if (mBtRouteProvider == null) return false;
- RoutingSessionInfo oldSessionInfo = mSessionInfos.isEmpty() ? null : mSessionInfos.get(0);
+ boolean updateSessionInfosIfNeeded() {
+ synchronized (mLock) {
+ // Prevent to execute this method before mBtRouteProvider is created.
+ if (mBtRouteProvider == null) return false;
+ RoutingSessionInfo oldSessionInfo = mSessionInfos.isEmpty() ? null : mSessionInfos.get(
+ 0);
- RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder(
- SYSTEM_SESSION_ID, "" /* clientPackageName */)
- .setSystemSession(true);
+ RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder(
+ SYSTEM_SESSION_ID, "" /* clientPackageName */)
+ .setSystemSession(true);
- MediaRoute2Info selectedRoute = mBtRouteProvider.getSelectedRoute();
- if (selectedRoute == null) {
- selectedRoute = mDefaultRoute;
- } else {
- builder.addTransferableRoute(mDefaultRoute.getId());
- }
- mSelectedRouteId = selectedRoute.getId();
- builder.addSelectedRoute(mSelectedRouteId);
+ MediaRoute2Info selectedRoute = mBtRouteProvider.getSelectedRoute();
+ if (selectedRoute == null) {
+ selectedRoute = mDefaultRoute;
+ } else {
+ builder.addTransferableRoute(mDefaultRoute.getId());
+ }
+ mSelectedRouteId = selectedRoute.getId();
+ builder.addSelectedRoute(mSelectedRouteId);
- for (MediaRoute2Info route : mBtRouteProvider.getTransferableRoutes()) {
- builder.addTransferableRoute(route.getId());
- }
+ for (MediaRoute2Info route : mBtRouteProvider.getTransferableRoutes()) {
+ builder.addTransferableRoute(route.getId());
+ }
- RoutingSessionInfo newSessionInfo = builder.setProviderId(mUniqueId).build();
- if (Objects.equals(oldSessionInfo, newSessionInfo)) {
- return false;
- } else {
- mSessionInfos.clear();
- mSessionInfos.add(newSessionInfo);
- return true;
+ RoutingSessionInfo newSessionInfo = builder.setProviderId(mUniqueId).build();
+ if (Objects.equals(oldSessionInfo, newSessionInfo)) {
+ return false;
+ } else {
+ mSessionInfos.clear();
+ mSessionInfos.add(newSessionInfo);
+ return true;
+ }
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 563dcf7..48f1ddb 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -21,7 +21,7 @@
import android.annotation.NonNull;
import android.net.Network;
import android.net.NetworkTemplate;
-import android.net.netstats.provider.AbstractNetworkStatsProvider;
+import android.net.netstats.provider.NetworkStatsProvider;
import android.telephony.SubscriptionPlan;
import java.util.Set;
@@ -130,8 +130,8 @@
Set<String> packageNames, int userId);
/**
- * Notifies that the specified {@link AbstractNetworkStatsProvider} has reached its quota
- * which was set through {@link AbstractNetworkStatsProvider#setLimit(String, long)}.
+ * Notifies that the specified {@link NetworkStatsProvider} has reached its quota
+ * which was set through {@link NetworkStatsProvider#onSetLimit(String, long)}.
*
* @param tag the human readable identifier of the custom network stats provider.
*/
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 0b1c91f..173dfc2 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -75,7 +75,7 @@
import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.TrafficStats.MB_IN_BYTES;
-import static android.net.netstats.provider.AbstractNetworkStatsProvider.QUOTA_UNLIMITED;
+import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
import static android.os.Trace.TRACE_TAG_NETWORK;
import static android.provider.Settings.Global.NETPOLICY_OVERRIDE_ENABLED;
import static android.provider.Settings.Global.NETPOLICY_QUOTA_ENABLED;
@@ -1868,8 +1868,11 @@
mNetIdToSubId.put(state.network.netId, parseSubId(state));
}
if (state.networkInfo != null && state.networkInfo.isConnected()) {
+ // Policies matched by NPMS only match by subscriber ID or by ssid. Thus subtype
+ // in the object created here is never used and its value doesn't matter, so use
+ // NETWORK_TYPE_UNKNOWN.
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state,
- true);
+ true, TelephonyManager.NETWORK_TYPE_UNKNOWN /* subType */);
identified.put(state, ident);
}
}
@@ -3087,17 +3090,38 @@
private void enforceSubscriptionPlanValidity(SubscriptionPlan[] plans) {
// nothing to check if no plans
if (plans.length == 0) {
+ Log.d(TAG, "Received empty plans list. Clearing existing SubscriptionPlans.");
return;
}
- final ArraySet<Integer> applicableNetworkTypes = new ArraySet<Integer>();
- boolean allNetworks = false;
- for (SubscriptionPlan plan : plans) {
- if (plan.getNetworkTypes() == null) {
- allNetworks = true;
+ final int[] allNetworkTypes = TelephonyManager.getAllNetworkTypes();
+ final ArraySet<Integer> allNetworksSet = new ArraySet<>();
+ addAll(allNetworksSet, allNetworkTypes);
+
+ final ArraySet<Integer> applicableNetworkTypes = new ArraySet<>();
+ boolean hasGeneralPlan = false;
+ for (int i = 0; i < plans.length; i++) {
+ final int[] planNetworkTypes = plans[i].getNetworkTypes();
+ final ArraySet<Integer> planNetworksSet = new ArraySet<>();
+ for (int j = 0; j < planNetworkTypes.length; j++) {
+ // ensure all network types are valid
+ if (allNetworksSet.contains(planNetworkTypes[j])) {
+ // ensure no duplicate network types in the same SubscriptionPlan
+ if (!planNetworksSet.add(planNetworkTypes[j])) {
+ throw new IllegalArgumentException(
+ "Subscription plan contains duplicate network types.");
+ }
+ } else {
+ throw new IllegalArgumentException("Invalid network type: "
+ + planNetworkTypes[j]);
+ }
+ }
+
+ if (planNetworkTypes.length == allNetworkTypes.length) {
+ hasGeneralPlan = true;
} else {
- final int[] networkTypes = plan.getNetworkTypes();
- if (!addAll(applicableNetworkTypes, networkTypes)) {
+ // ensure no network type applies to multiple plans
+ if (!addAll(applicableNetworkTypes, planNetworkTypes)) {
throw new IllegalArgumentException(
"Multiple subscription plans defined for a single network type.");
}
@@ -3105,7 +3129,7 @@
}
// ensure at least one plan applies for every network type
- if (!allNetworks) {
+ if (!hasGeneralPlan) {
throw new IllegalArgumentException(
"No generic subscription plan that applies to all network types.");
}
@@ -3114,12 +3138,12 @@
/**
* Adds all of the {@code elements} to the {@code set}.
*
- * @return {@code false} if any element is not added because the set already have the value.
+ * @return {@code false} if any element is not added because the set already has the value.
*/
- private static boolean addAll(@NonNull Set<Integer> set, @NonNull int... elements) {
+ private static boolean addAll(@NonNull ArraySet<Integer> set, @NonNull int... elements) {
boolean result = true;
- for (int element : elements) {
- result &= set.add(element);
+ for (int i = 0; i < elements.length; i++) {
+ result &= set.add(elements[i]);
}
return result;
}
@@ -3329,6 +3353,7 @@
* existing plans; it simply lets the debug package define new plans.
*/
void setSubscriptionPlansOwner(int subId, String packageName) {
+ mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);
SystemProperties.set(PROP_SUB_PLAN_OWNER + "." + subId, packageName);
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index 22b01be..75ffe35 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -229,7 +229,7 @@
entry.txPackets += reader.nextLong();
}
- stats.addEntry(entry);
+ stats.insertEntry(entry);
reader.finishLine();
}
} catch (NullPointerException|NumberFormatException e) {
@@ -279,7 +279,7 @@
entry.txBytes = reader.nextLong();
entry.txPackets = reader.nextLong();
- stats.addEntry(entry);
+ stats.insertEntry(entry);
reader.finishLine();
}
} catch (NullPointerException|NumberFormatException e) {
@@ -439,7 +439,7 @@
if ((limitIfaces == null || ArrayUtils.contains(limitIfaces, entry.iface))
&& (limitUid == UID_ALL || limitUid == entry.uid)
&& (limitTag == TAG_ALL || limitTag == entry.tag)) {
- stats.addEntry(entry);
+ stats.insertEntry(entry);
}
reader.finishLine();
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index cb3da91..d8264b3 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -17,6 +17,7 @@
package com.android.server.net;
import static android.Manifest.permission.ACCESS_NETWORK_STATE;
+import static android.Manifest.permission.NETWORK_STATS_PROVIDER;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.content.Intent.ACTION_SHUTDOWN;
@@ -26,6 +27,7 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
import static android.net.ConnectivityManager.isNetworkTypeMobile;
+import static android.net.NetworkIdentity.SUBTYPE_COMBINED;
import static android.net.NetworkStack.checkNetworkStackPermission;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.IFACE_ALL;
@@ -44,10 +46,12 @@
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
+import static android.net.NetworkTemplate.getCollapsedRatType;
import static android.net.TrafficStats.KB_IN_BYTES;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.os.Trace.TRACE_TAG_NETWORK;
import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED;
+import static android.provider.Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED;
import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES;
@@ -63,6 +67,9 @@
import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
+import static android.telephony.PhoneStateListener.LISTEN_NONE;
+import static android.telephony.PhoneStateListener.LISTEN_SERVICE_STATE;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
@@ -102,12 +109,13 @@
import android.net.TrafficStats;
import android.net.netstats.provider.INetworkStatsProvider;
import android.net.netstats.provider.INetworkStatsProviderCallback;
-import android.net.netstats.provider.NetworkStatsProviderCallback;
+import android.net.netstats.provider.NetworkStatsProvider;
import android.os.BestClock;
import android.os.Binder;
import android.os.DropBoxManager;
import android.os.Environment;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.INetworkManagementService;
@@ -124,6 +132,8 @@
import android.provider.Settings.Global;
import android.service.NetworkInterfaceProto;
import android.service.NetworkStatsServiceDumpProto;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
import android.telephony.SubscriptionPlan;
import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
@@ -156,6 +166,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -172,6 +183,7 @@
private static final int MSG_PERFORM_POLL = 1;
// Perform polling, persist network, and register the global alert again.
private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2;
+ private static final int MSG_UPDATE_IFACES = 3;
/** Flags to control detail level of poll event. */
private static final int FLAG_PERSIST_NETWORK = 0x1;
@@ -228,12 +240,20 @@
* Settings that can be changed externally.
*/
public interface NetworkStatsSettings {
- public long getPollInterval();
- public long getPollDelay();
- public boolean getSampleEnabled();
- public boolean getAugmentEnabled();
+ long getPollInterval();
+ long getPollDelay();
+ boolean getSampleEnabled();
+ boolean getAugmentEnabled();
+ /**
+ * When enabled, all mobile data is reported under {@link NetworkIdentity#SUBTYPE_COMBINED}.
+ * When disabled, mobile data is broken down by a granular subtype representative of the
+ * actual subtype. {@see NetworkTemplate#getCollapsedRatType}.
+ * Enabling this decreases the level of detail but saves performance, disk space and
+ * amount of data logged.
+ */
+ boolean getCombineSubtypeEnabled();
- public static class Config {
+ class Config {
public final long bucketDuration;
public final long rotateAgeMillis;
public final long deleteAgeMillis;
@@ -245,16 +265,16 @@
}
}
- public Config getDevConfig();
- public Config getXtConfig();
- public Config getUidConfig();
- public Config getUidTagConfig();
+ Config getDevConfig();
+ Config getXtConfig();
+ Config getUidConfig();
+ Config getUidTagConfig();
- public long getGlobalAlertBytes(long def);
- public long getDevPersistBytes(long def);
- public long getXtPersistBytes(long def);
- public long getUidPersistBytes(long def);
- public long getUidTagPersistBytes(long def);
+ long getGlobalAlertBytes(long def);
+ long getDevPersistBytes(long def);
+ long getXtPersistBytes(long def);
+ long getUidPersistBytes(long def);
+ long getUidTagPersistBytes(long def);
}
private final Object mStatsLock = new Object();
@@ -279,6 +299,11 @@
@GuardedBy("mStatsLock")
private Network[] mDefaultNetworks = new Network[0];
+ /** Last states of all networks sent from ConnectivityService. */
+ @GuardedBy("mStatsLock")
+ @Nullable
+ private NetworkState[] mLastNetworkStates = null;
+
private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
new DropBoxNonMonotonicObserver();
@@ -354,6 +379,12 @@
performPoll(FLAG_PERSIST_ALL);
break;
}
+ case MSG_UPDATE_IFACES: {
+ // If no cached states, ignore.
+ if (mLastNetworkStates == null) break;
+ updateIfaces(mDefaultNetworks, mLastNetworkStates, mActiveIface);
+ break;
+ }
case MSG_PERFORM_POLL_REGISTER_ALERT: {
performPoll(FLAG_PERSIST_NETWORK);
registerGlobalAlert();
@@ -406,6 +437,7 @@
final HandlerThread handlerThread = mDeps.makeHandlerThread();
handlerThread.start();
mHandler = new NetworkStatsHandler(handlerThread.getLooper());
+ mPhoneListener = new NetworkTypeListener(new HandlerExecutor(mHandler));
}
/**
@@ -485,6 +517,13 @@
mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
mSettings.getPollInterval(), pollIntent);
+ // TODO: 1. listen to changes from all subscriptions.
+ // 2. listen to settings changed to support dynamically enable/disable.
+ // watch for networkType changes
+ if (!mSettings.getCombineSubtypeEnabled()) {
+ mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE);
+ }
+
registerGlobalAlert();
}
@@ -505,6 +544,8 @@
mContext.unregisterReceiver(mUserReceiver);
mContext.unregisterReceiver(mShutdownReceiver);
+ mTeleManager.listen(mPhoneListener, LISTEN_NONE);
+
final long currentTime = mClock.millis();
// persist any pending stats
@@ -557,7 +598,7 @@
} catch (RemoteException e) {
// ignored; service lives in system_server
}
- invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.setAlert(mGlobalAlertBytes));
+ invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetAlert(mGlobalAlertBytes));
}
@Override
@@ -758,7 +799,7 @@
final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
final NetworkStats stats = new NetworkStats(end - start, 1);
- stats.addEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE,
+ stats.insertEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE,
METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets,
entry.txBytes, entry.txPackets, entry.operations));
return stats;
@@ -1155,6 +1196,38 @@
}
};
+ /**
+ * Receiver that watches for {@link TelephonyManager} changes, such as
+ * transitioning between Radio Access Technology(RAT) types.
+ */
+ @NonNull
+ private final NetworkTypeListener mPhoneListener;
+
+ class NetworkTypeListener extends PhoneStateListener {
+ private volatile int mLastCollapsedRatType = NETWORK_TYPE_UNKNOWN;
+
+ NetworkTypeListener(@NonNull Executor executor) {
+ super(executor);
+ }
+
+ @Override
+ public void onServiceStateChanged(@NonNull ServiceState ss) {
+ final int networkType = ss.getDataNetworkType();
+ final int collapsedRatType = getCollapsedRatType(networkType);
+ if (collapsedRatType == mLastCollapsedRatType) return;
+
+ if (LOGD) {
+ Log.d(TAG, "subtype changed for mobile: "
+ + mLastCollapsedRatType + " -> " + collapsedRatType);
+ }
+ // Protect service from frequently updating. Remove pending messages if any.
+ mHandler.removeMessages(MSG_UPDATE_IFACES);
+ mLastCollapsedRatType = collapsedRatType;
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay());
+ }
+ }
+
private void updateIfaces(
Network[] defaultNetworks,
NetworkState[] networkStates,
@@ -1176,7 +1249,8 @@
* they are combined under a single {@link NetworkIdentitySet}.
*/
@GuardedBy("mStatsLock")
- private void updateIfacesLocked(Network[] defaultNetworks, NetworkState[] states) {
+ private void updateIfacesLocked(@Nullable Network[] defaultNetworks,
+ @NonNull NetworkState[] states) {
if (!mSystemReady) return;
if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
@@ -1196,13 +1270,18 @@
mDefaultNetworks = defaultNetworks;
}
+ mLastNetworkStates = states;
+
+ final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled();
final ArraySet<String> mobileIfaces = new ArraySet<>();
for (NetworkState state : states) {
if (state.networkInfo.isConnected()) {
final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType());
final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network);
+ final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED
+ : getSubTypeForState(state);
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state,
- isDefault);
+ isDefault, subType);
// Traffic occurring on the base interface is always counted for
// both total usage and UID details.
@@ -1263,6 +1342,20 @@
mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]);
}
+ /**
+ * For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through
+ * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different
+ * transport types do not actually fill this value.
+ */
+ private int getSubTypeForState(@NonNull NetworkState state) {
+ if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ return 0;
+ }
+
+ // TODO: return different subType for different subscriptions.
+ return mPhoneListener.mLastCollapsedRatType;
+ }
+
private static <K> NetworkIdentitySet findOrCreateNetworkIdentitySet(
ArrayMap<K, NetworkIdentitySet> map, K key) {
NetworkIdentitySet ident = map.get(key);
@@ -1375,7 +1468,8 @@
Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate");
final int registeredCallbackCount = mStatsProviderCbList.getRegisteredCallbackCount();
mStatsProviderSem.drainPermits();
- invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.requestStatsUpdate(0 /* unused */));
+ invokeForAllStatsProviderCallbacks(
+ (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */));
try {
mStatsProviderSem.tryAcquire(registeredCallbackCount,
MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS);
@@ -1550,7 +1644,7 @@
@Override
public void setStatsProviderLimitAsync(@NonNull String iface, long quota) {
Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")");
- invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.setLimit(iface, quota));
+ invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetLimit(iface, quota));
}
}
@@ -1615,6 +1709,12 @@
return;
}
+ pw.println("Configs:");
+ pw.increaseIndent();
+ pw.printPair(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled());
+ pw.println();
+ pw.decreaseIndent();
+
pw.println("Active interfaces:");
pw.increaseIndent();
for (int i = 0; i < mActiveIfaces.size(); i++) {
@@ -1794,7 +1894,7 @@
}
}
- // TODO: It is copied from ConnectivitySerivce, consider refactor these check permission
+ // TODO: It is copied from ConnectivityService, consider refactor these check permission
// functions to a proper util.
private boolean checkAnyPermissionOf(String... permissions) {
for (String permission : permissions) {
@@ -1819,16 +1919,15 @@
*
* @param tag a human readable identifier of the custom network stats provider.
* @param provider the {@link INetworkStatsProvider} binder corresponding to the
- * {@link android.net.netstats.provider.AbstractNetworkStatsProvider} to be
- * registered.
+ * {@link NetworkStatsProvider} to be registered.
*
- * @return a binder interface of
- * {@link android.net.netstats.provider.NetworkStatsProviderCallback}, which can be
- * used to report events to the system.
+ * @return a {@link INetworkStatsProviderCallback} binder
+ * interface, which can be used to report events to the system.
*/
public @NonNull INetworkStatsProviderCallback registerNetworkStatsProvider(
@NonNull String tag, @NonNull INetworkStatsProvider provider) {
- mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG);
+ enforceAnyPermissionOf(NETWORK_STATS_PROVIDER,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
Objects.requireNonNull(provider, "provider is null");
Objects.requireNonNull(tag, "tag is null");
try {
@@ -1929,7 +2028,7 @@
}
@Override
- public void onStatsUpdated(int token, @Nullable NetworkStats ifaceStats,
+ public void notifyStatsUpdated(int token, @Nullable NetworkStats ifaceStats,
@Nullable NetworkStats uidStats) {
// TODO: 1. Use token to map ifaces to correct NetworkIdentity.
// 2. Store the difference and store it directly to the recorder.
@@ -1941,12 +2040,12 @@
}
@Override
- public void onAlertReached() throws RemoteException {
+ public void notifyAlertReached() throws RemoteException {
mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */);
}
@Override
- public void onLimitReached() {
+ public void notifyLimitReached() {
Log.d(TAG, mTag + ": onLimitReached");
LocalServices.getService(NetworkPolicyManagerInternal.class)
.onStatsProviderLimitReached(mTag);
@@ -2044,6 +2143,10 @@
return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true);
}
@Override
+ public boolean getCombineSubtypeEnabled() {
+ return getGlobalBoolean(NETSTATS_COMBINE_SUBTYPE_ENABLED, false);
+ }
+ @Override
public Config getDevConfig() {
return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index f45e66e..2853956 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -141,6 +141,7 @@
updateDefaultAutomaticRuleNames();
mConfig = mDefaultConfig.copy();
mConfigs.put(UserHandle.USER_SYSTEM, mConfig);
+ mConsolidatedPolicy = mConfig.toNotificationPolicy();
mSettingsObserver = new SettingsObserver(mHandler);
mSettingsObserver.observe();
@@ -821,9 +822,6 @@
* @return a copy of the zen mode consolidated policy
*/
public Policy getConsolidatedNotificationPolicy() {
- if (mConsolidatedPolicy == null) {
- return null;
- }
return mConsolidatedPolicy.copy();
}
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 79a4da2..690b9f7 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -481,6 +481,12 @@
mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
}
}
+ // if either package instruments the other, mark both as visible to one another
+ if (pkgInstruments(newPkgSetting, existingSetting)
+ || pkgInstruments(existingSetting, newPkgSetting)) {
+ mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
+ mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId);
+ }
}
int existingSize = existingSettings.size();
@@ -715,19 +721,6 @@
Trace.endSection();
}
- if (callingPkgSetting != null) {
- if (callingPkgInstruments(callingPkgSetting, targetPkgSetting, targetName)) {
- return false;
- }
- } else {
- for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) {
- if (callingPkgInstruments(callingSharedPkgSettings.valueAt(i),
- targetPkgSetting, targetName)) {
- return false;
- }
- }
- }
-
try {
Trace.beginSection("mOverlayReferenceMapper");
if (callingSharedPkgSettings != null) {
@@ -762,16 +755,16 @@
}
}
- private static boolean callingPkgInstruments(PackageSetting callingPkgSetting,
- PackageSetting targetPkgSetting,
- String targetName) {
+ /** Returns {@code true} if the source package instruments the target package. */
+ private static boolean pkgInstruments(PackageSetting source, PackageSetting target) {
try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "callingPkgInstruments");
- final List<ParsedInstrumentation> inst = callingPkgSetting.pkg.getInstrumentations();
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "pkgInstruments");
+ final String packageName = target.pkg.getPackageName();
+ final List<ParsedInstrumentation> inst = source.pkg.getInstrumentations();
for (int i = ArrayUtils.size(inst) - 1; i >= 0; i--) {
- if (Objects.equals(inst.get(i).getTargetPackage(), targetName)) {
+ if (Objects.equals(inst.get(i).getTargetPackage(), packageName)) {
if (DEBUG_LOGGING) {
- log(callingPkgSetting, targetPkgSetting, "instrumentation");
+ log(source, target, "instrumentation");
}
return true;
}
diff --git a/services/core/java/com/android/server/pm/DataLoaderManagerService.java b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
index 8eb773a..09baf6e 100644
--- a/services/core/java/com/android/server/pm/DataLoaderManagerService.java
+++ b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
@@ -213,7 +213,7 @@
void destroy() {
try {
- mDataLoader.destroy();
+ mDataLoader.destroy(mId);
} catch (RemoteException ignored) {
}
mContext.unbindService(this);
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 8031eaa..1b271a7 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -819,6 +819,18 @@
}
@Override
+ public String getShortcutIconUri(String callingPackage, String packageName,
+ String shortcutId, int userId) {
+ ensureShortcutPermission(callingPackage);
+ if (!canAccessProfile(userId, "Cannot access shortcuts")) {
+ return null;
+ }
+
+ return mShortcutServiceInternal.getShortcutIconUri(getCallingUserId(), callingPackage,
+ packageName, shortcutId, userId);
+ }
+
+ @Override
public boolean hasShortcutHostPermission(String callingPackage) {
verifyCallingPackage(callingPackage);
return mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index cdc3736..2ff3d2a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -47,7 +47,6 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
-import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
@@ -1038,80 +1037,11 @@
}
}
- static void sendPendingStreaming(Context context, IntentSender target, int sessionId,
- Throwable cause) {
- final Intent intent = new Intent();
- intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
- intent.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_STREAMING);
- if (cause != null && !TextUtils.isEmpty(cause.getMessage())) {
- intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
- "Staging Image Not Ready [" + cause.getMessage() + "]");
- } else {
- intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, "Staging Image Not Ready");
- }
- try {
- target.sendIntent(context, 0, intent, null, null);
- } catch (SendIntentException ignored) {
- }
- }
-
- static void sendOnUserActionRequired(Context context, IntentSender target, int sessionId,
- Intent intent) {
- final Intent fillIn = new Intent();
- fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
- fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_USER_ACTION);
- fillIn.putExtra(Intent.EXTRA_INTENT, intent);
- try {
- target.sendIntent(context, 0, fillIn, null, null);
- } catch (SendIntentException ignored) {
- }
- }
-
- static void sendOnPackageInstalled(Context context, IntentSender target, int sessionId,
- boolean showNotification, int userId, String basePackageName, int returnCode,
- String msg, Bundle extras) {
- if (PackageManager.INSTALL_SUCCEEDED == returnCode && showNotification) {
- boolean update = (extras != null) && extras.getBoolean(Intent.EXTRA_REPLACING);
- Notification notification = buildSuccessNotification(context,
- context.getResources()
- .getString(update ? R.string.package_updated_device_owner :
- R.string.package_installed_device_owner),
- basePackageName,
- userId);
- if (notification != null) {
- NotificationManager notificationManager = (NotificationManager)
- context.getSystemService(Context.NOTIFICATION_SERVICE);
- notificationManager.notify(basePackageName,
- SystemMessage.NOTE_PACKAGE_STATE,
- notification);
- }
- }
- final Intent fillIn = new Intent();
- fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, basePackageName);
- fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
- fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
- PackageManager.installStatusToPublicStatus(returnCode));
- fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
- PackageManager.installStatusToString(returnCode, msg));
- fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
- if (extras != null) {
- final String existing = extras.getString(
- PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
- if (!TextUtils.isEmpty(existing)) {
- fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing);
- }
- }
- try {
- target.sendIntent(context, 0, fillIn, null, null);
- } catch (SendIntentException ignored) {
- }
- }
-
/**
* Build a notification for package installation / deletion by device owners that is shown if
* the operation succeeds.
*/
- private static Notification buildSuccessNotification(Context context, String contentText,
+ static Notification buildSuccessNotification(Context context, String contentText,
String basePackageName, int userId) {
PackageInfo packageInfo = null;
try {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 28d7c13..348a4cb 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -51,6 +51,8 @@
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.NotificationManager;
import android.app.admin.DevicePolicyEventLogger;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.ComponentName;
@@ -119,9 +121,11 @@
import android.util.SparseIntArray;
import android.util.apk.ApkSignatureVerifier;
+import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
+import com.android.internal.messages.nano.SystemMessageProto;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
@@ -440,8 +444,7 @@
final int returnCode = args.argi1;
args.recycle();
- PackageInstallerService.sendOnPackageInstalled(mContext,
- statusReceiver, sessionId,
+ sendOnPackageInstalled(mContext, statusReceiver, sessionId,
isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId,
packageName, returnCode, message, extras);
@@ -1484,6 +1487,18 @@
return e;
}
+ private void onDataLoaderUnrecoverable() {
+ final PackageManagerService packageManagerService = mPm;
+ final String packageName = mPackageName;
+ mHandler.post(() -> {
+ if (packageManagerService.deletePackageX(packageName,
+ PackageManager.VERSION_CODE_HIGHEST, UserHandle.USER_SYSTEM,
+ PackageManager.DELETE_ALL_USERS) != PackageManager.DELETE_SUCCEEDED) {
+ Slog.e(TAG, "Failed to uninstall package with failed dataloader: " + packageName);
+ }
+ });
+ }
+
/**
* If session should be sealed, then it's sealed to prevent further modification.
* If the session can't be sealed then it's destroyed.
@@ -1636,8 +1651,7 @@
}
}
if (!success) {
- PackageInstallerService.sendOnPackageInstalled(mContext,
- mRemoteStatusReceiver, sessionId,
+ sendOnPackageInstalled(mContext, mRemoteStatusReceiver, sessionId,
isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId, null,
failure.error, failure.getLocalizedMessage(), null);
return;
@@ -1684,8 +1698,7 @@
intent.setPackage(mPm.getPackageInstallerPackageName());
intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
- PackageInstallerService.sendOnUserActionRequired(mContext,
- mRemoteStatusReceiver, sessionId, intent);
+ sendOnUserActionRequired(mContext, mRemoteStatusReceiver, sessionId, intent);
// Commit was keeping session marked as active until now; release
// that extra refcount so session appears idle.
@@ -2563,11 +2576,20 @@
IDataLoaderStatusListener listener = new IDataLoaderStatusListener.Stub() {
@Override
public void onStatusChanged(int dataLoaderId, int status) {
- try {
- if (status == IDataLoaderStatusListener.DATA_LOADER_DESTROYED) {
+ switch (status) {
+ case IDataLoaderStatusListener.DATA_LOADER_STOPPED:
+ case IDataLoaderStatusListener.DATA_LOADER_DESTROYED:
return;
- }
+ case IDataLoaderStatusListener.DATA_LOADER_UNRECOVERABLE:
+ onDataLoaderUnrecoverable();
+ return;
+ }
+ if (mDestroyed || mDataLoaderFinished) {
+ return;
+ }
+
+ try {
IDataLoader dataLoader = dataLoaderManager.getDataLoader(dataLoaderId);
if (dataLoader == null) {
mDataLoaderFinished = true;
@@ -2582,12 +2604,13 @@
if (manualStartAndDestroy) {
// IncrementalFileStorages will call start after all files are
// created in IncFS.
- dataLoader.start();
+ dataLoader.start(dataLoaderId);
}
break;
}
case IDataLoaderStatusListener.DATA_LOADER_STARTED: {
dataLoader.prepareImage(
+ dataLoaderId,
addedFiles.toArray(
new InstallationFileParcel[addedFiles.size()]),
removedFiles.toArray(new String[removedFiles.size()]));
@@ -2602,7 +2625,7 @@
dispatchStreamValidateAndCommit();
}
if (manualStartAndDestroy) {
- dataLoader.destroy();
+ dataLoader.destroy(dataLoaderId);
}
break;
}
@@ -2612,7 +2635,7 @@
new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"Failed to prepare image."));
if (manualStartAndDestroy) {
- dataLoader.destroy();
+ dataLoader.destroy(dataLoaderId);
}
break;
}
@@ -2620,9 +2643,8 @@
} catch (RemoteException e) {
// In case of streaming failure we don't want to fail or commit the session.
// Just return from this method and allow caller to commit again.
- PackageInstallerService.sendPendingStreaming(mContext,
- mRemoteStatusReceiver,
- sessionId, new StreamingException(e));
+ sendPendingStreaming(mContext, mRemoteStatusReceiver, sessionId,
+ new StreamingException(e));
}
}
};
@@ -2924,6 +2946,75 @@
pw.decreaseIndent();
}
+ private static void sendOnUserActionRequired(Context context, IntentSender target,
+ int sessionId, Intent intent) {
+ final Intent fillIn = new Intent();
+ fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
+ fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_USER_ACTION);
+ fillIn.putExtra(Intent.EXTRA_INTENT, intent);
+ try {
+ target.sendIntent(context, 0, fillIn, null, null);
+ } catch (IntentSender.SendIntentException ignored) {
+ }
+ }
+
+ private static void sendOnPackageInstalled(Context context, IntentSender target, int sessionId,
+ boolean showNotification, int userId, String basePackageName, int returnCode,
+ String msg, Bundle extras) {
+ if (PackageManager.INSTALL_SUCCEEDED == returnCode && showNotification) {
+ boolean update = (extras != null) && extras.getBoolean(Intent.EXTRA_REPLACING);
+ Notification notification = PackageInstallerService.buildSuccessNotification(context,
+ context.getResources()
+ .getString(update ? R.string.package_updated_device_owner :
+ R.string.package_installed_device_owner),
+ basePackageName,
+ userId);
+ if (notification != null) {
+ NotificationManager notificationManager = (NotificationManager)
+ context.getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.notify(basePackageName,
+ SystemMessageProto.SystemMessage.NOTE_PACKAGE_STATE,
+ notification);
+ }
+ }
+ final Intent fillIn = new Intent();
+ fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, basePackageName);
+ fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
+ fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
+ PackageManager.installStatusToPublicStatus(returnCode));
+ fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
+ PackageManager.installStatusToString(returnCode, msg));
+ fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
+ if (extras != null) {
+ final String existing = extras.getString(
+ PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
+ if (!TextUtils.isEmpty(existing)) {
+ fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing);
+ }
+ }
+ try {
+ target.sendIntent(context, 0, fillIn, null, null);
+ } catch (IntentSender.SendIntentException ignored) {
+ }
+ }
+
+ private static void sendPendingStreaming(Context context, IntentSender target, int sessionId,
+ Throwable cause) {
+ final Intent intent = new Intent();
+ intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
+ intent.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_STREAMING);
+ if (cause != null && !TextUtils.isEmpty(cause.getMessage())) {
+ intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
+ "Staging Image Not Ready [" + cause.getMessage() + "]");
+ } else {
+ intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, "Staging Image Not Ready");
+ }
+ try {
+ target.sendIntent(context, 0, intent, null, null);
+ } catch (IntentSender.SendIntentException ignored) {
+ }
+ }
+
private static void writeGrantedRuntimePermissionsLocked(XmlSerializer out,
String[] grantedRuntimePermissions) throws IOException {
if (grantedRuntimePermissions != null) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 24ebd32..09e4e60 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1548,7 +1548,6 @@
final @Nullable String mConfiguratorPackage;
final @Nullable String mAppPredictionServicePackage;
final @Nullable String mIncidentReportApproverPackage;
- final @Nullable String[] mTelephonyPackages;
final @Nullable String mServicesExtensionPackageName;
final @Nullable String mSharedSystemSharedLibraryPackageName;
final @Nullable String mRetailDemoPackage;
@@ -3181,7 +3180,6 @@
mConfiguratorPackage = getDeviceConfiguratorPackageName();
mAppPredictionServicePackage = getAppPredictionServicePackageName();
mIncidentReportApproverPackage = getIncidentReportApproverPackageName();
- mTelephonyPackages = getTelephonyPackageNames();
mRetailDemoPackage = getRetailDemoPackageName();
// Now that we know all of the shared libraries, update all clients to have
@@ -19939,16 +19937,6 @@
}
@Override
- public String[] getTelephonyPackageNames() {
- String names = mContext.getString(R.string.config_telephonyPackages);
- String[] telephonyPackageNames = null;
- if (!TextUtils.isEmpty(names)) {
- telephonyPackageNames = names.trim().split(",");
- }
- return ensureSystemPackageNames(telephonyPackageNames);
- }
-
- @Override
public String getContentCaptureServicePackageName() {
final String flattenedContentCaptureService =
mContext.getString(R.string.config_defaultContentCaptureService);
@@ -23335,8 +23323,6 @@
return filterOnlySystemPackages(mIncidentReportApproverPackage);
case PackageManagerInternal.PACKAGE_APP_PREDICTOR:
return filterOnlySystemPackages(mAppPredictionServicePackage);
- case PackageManagerInternal.PACKAGE_TELEPHONY:
- return filterOnlySystemPackages(mTelephonyPackages);
case PackageManagerInternal.PACKAGE_COMPANION:
return filterOnlySystemPackages("com.android.companiondevicemanager");
case PackageManagerInternal.PACKAGE_RETAIL_DEMO:
diff --git a/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java b/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
index dc534a7..1c5f0a7 100644
--- a/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
+++ b/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
@@ -28,7 +28,6 @@
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.Preconditions;
import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
import libcore.io.IoUtils;
@@ -150,9 +149,10 @@
shortcut.setIconResourceId(0);
shortcut.setIconResName(null);
shortcut.setBitmapPath(null);
+ shortcut.setIconUri(null);
shortcut.clearFlags(ShortcutInfo.FLAG_HAS_ICON_FILE |
ShortcutInfo.FLAG_ADAPTIVE_BITMAP | ShortcutInfo.FLAG_HAS_ICON_RES |
- ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE);
+ ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE | ShortcutInfo.FLAG_HAS_ICON_URI);
}
public void saveBitmapLocked(ShortcutInfo shortcut,
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index c8df5c7..1fc0a38 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -102,6 +102,7 @@
private static final String ATTR_ICON_RES_ID = "icon-res";
private static final String ATTR_ICON_RES_NAME = "icon-resname";
private static final String ATTR_BITMAP_PATH = "bitmap-path";
+ private static final String ATTR_ICON_URI = "icon-uri";
private static final String ATTR_LOCUS_ID = "locus-id";
private static final String ATTR_PERSON_NAME = "name";
@@ -1628,7 +1629,8 @@
int flags = si.getFlags() &
~(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES
| ShortcutInfo.FLAG_ICON_FILE_PENDING_SAVE
- | ShortcutInfo.FLAG_DYNAMIC);
+ | ShortcutInfo.FLAG_DYNAMIC
+ | ShortcutInfo.FLAG_HAS_ICON_URI | ShortcutInfo.FLAG_ADAPTIVE_BITMAP);
ShortcutService.writeAttr(out, ATTR_FLAGS, flags);
// Set the publisher version code at every backup.
@@ -1646,6 +1648,7 @@
ShortcutService.writeAttr(out, ATTR_ICON_RES_ID, si.getIconResourceId());
ShortcutService.writeAttr(out, ATTR_ICON_RES_NAME, si.getIconResName());
ShortcutService.writeAttr(out, ATTR_BITMAP_PATH, si.getBitmapPath());
+ ShortcutService.writeAttr(out, ATTR_ICON_URI, si.getIconUri());
}
if (shouldBackupDetails) {
@@ -1764,6 +1767,7 @@
int iconResId;
String iconResName;
String bitmapPath;
+ String iconUri;
final String locusIdString;
int backupVersionCode;
ArraySet<String> categories = null;
@@ -1791,6 +1795,7 @@
iconResId = (int) ShortcutService.parseLongAttribute(parser, ATTR_ICON_RES_ID);
iconResName = ShortcutService.parseStringAttribute(parser, ATTR_ICON_RES_NAME);
bitmapPath = ShortcutService.parseStringAttribute(parser, ATTR_BITMAP_PATH);
+ iconUri = ShortcutService.parseStringAttribute(parser, ATTR_ICON_URI);
locusIdString = ShortcutService.parseStringAttribute(parser, ATTR_LOCUS_ID);
final int outerDepth = parser.getDepth();
@@ -1866,8 +1871,8 @@
categories,
intents.toArray(new Intent[intents.size()]),
rank, extras, lastChangedTimestamp, flags,
- iconResId, iconResName, bitmapPath, disabledReason,
- persons.toArray(new Person[persons.size()]), locusId);
+ iconResId, iconResName, bitmapPath, iconUri,
+ disabledReason, persons.toArray(new Person[persons.size()]), locusId);
}
private static Intent parseIntent(XmlPullParser parser)
@@ -1991,16 +1996,26 @@
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " still has an icon");
}
- if (si.hasAdaptiveBitmap() && !si.hasIconFile()) {
+ if (si.hasAdaptiveBitmap() && !(si.hasIconFile() || si.hasIconUri())) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
- + " has adaptive bitmap but was not saved to a file.");
+ + " has adaptive bitmap but was not saved to a file nor has icon uri.");
}
if (si.hasIconFile() && si.hasIconResource()) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " has both resource and bitmap icons");
}
+ if (si.hasIconFile() && si.hasIconUri()) {
+ failed = true;
+ Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ + " has both url and bitmap icons");
+ }
+ if (si.hasIconUri() && si.hasIconResource()) {
+ failed = true;
+ Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ + " has both url and resource icons");
+ }
if (si.isEnabled()
!= (si.getDisabledReason() == ShortcutInfo.DISABLED_REASON_NOT_DISABLED)) {
failed = true;
diff --git a/services/core/java/com/android/server/pm/ShortcutParser.java b/services/core/java/com/android/server/pm/ShortcutParser.java
index f9c0db0..d3aace1 100644
--- a/services/core/java/com/android/server/pm/ShortcutParser.java
+++ b/services/core/java/com/android/server/pm/ShortcutParser.java
@@ -449,6 +449,7 @@
iconResId,
null, // icon res name
null, // bitmap path
+ null, // icon Url
disabledReason,
null /* persons */,
null /* locusId */);
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 66f3574..8768ab0 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -24,6 +24,8 @@
import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
import android.app.IUidObserver;
+import android.app.IUriGrantsManager;
+import android.app.UriGrantsManager;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
@@ -65,6 +67,7 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
+import android.os.IBinder;
import android.os.LocaleList;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
@@ -106,6 +109,7 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.ShortcutUser.PackageWithUser;
+import com.android.server.uri.UriGrantsManagerInternal;
import libcore.io.IoUtils;
@@ -327,6 +331,9 @@
private final UserManagerInternal mUserManagerInternal;
private final UsageStatsManagerInternal mUsageStatsManagerInternal;
private final ActivityManagerInternal mActivityManagerInternal;
+ private final IUriGrantsManager mUriGrantsManager;
+ private final UriGrantsManagerInternal mUriGrantsManagerInternal;
+ private final IBinder mUriPermissionOwner;
private final ShortcutRequestPinProcessor mShortcutRequestPinProcessor;
private final ShortcutBitmapSaver mShortcutBitmapSaver;
@@ -449,6 +456,11 @@
mActivityManagerInternal = Objects.requireNonNull(
LocalServices.getService(ActivityManagerInternal.class));
+ mUriGrantsManager = UriGrantsManager.getService();
+ mUriGrantsManagerInternal = Objects.requireNonNull(
+ LocalServices.getService(UriGrantsManagerInternal.class));
+ mUriPermissionOwner = mUriGrantsManagerInternal.newUriPermissionOwner(TAG);
+
mShortcutRequestPinProcessor = new ShortcutRequestPinProcessor(this, mLock);
mShortcutBitmapSaver = new ShortcutBitmapSaver(this);
mShortcutDumpFiles = new ShortcutDumpFiles(this);
@@ -1414,7 +1426,7 @@
}
void saveIconAndFixUpShortcutLocked(ShortcutInfo shortcut) {
- if (shortcut.hasIconFile() || shortcut.hasIconResource()) {
+ if (shortcut.hasIconFile() || shortcut.hasIconResource() || shortcut.hasIconUri()) {
return;
}
@@ -1438,6 +1450,15 @@
shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_RES);
return;
}
+ case Icon.TYPE_URI:
+ shortcut.setIconUri(icon.getUriString());
+ shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_URI);
+ return;
+ case Icon.TYPE_URI_ADAPTIVE_BITMAP:
+ shortcut.setIconUri(icon.getUriString());
+ shortcut.addFlags(ShortcutInfo.FLAG_HAS_ICON_URI
+ | ShortcutInfo.FLAG_ADAPTIVE_BITMAP);
+ return;
case Icon.TYPE_BITMAP:
bitmap = icon.getBitmap(); // Don't recycle in this case.
break;
@@ -3129,6 +3150,59 @@
}
@Override
+ public String getShortcutIconUri(int launcherUserId, @NonNull String launcherPackage,
+ @NonNull String packageName, @NonNull String shortcutId, int userId) {
+ Objects.requireNonNull(launcherPackage, "launcherPackage");
+ Objects.requireNonNull(packageName, "packageName");
+ Objects.requireNonNull(shortcutId, "shortcutId");
+
+ synchronized (mLock) {
+ throwIfUserLockedL(userId);
+ throwIfUserLockedL(launcherUserId);
+
+ getLauncherShortcutsLocked(launcherPackage, userId, launcherUserId)
+ .attemptToRestoreIfNeededAndSave();
+
+ final ShortcutPackage p = getUserShortcutsLocked(userId)
+ .getPackageShortcutsIfExists(packageName);
+ if (p == null) {
+ return null;
+ }
+
+ final ShortcutInfo shortcutInfo = p.findShortcutById(shortcutId);
+ if (shortcutInfo == null || !shortcutInfo.hasIconUri()) {
+ return null;
+ }
+ String uri = shortcutInfo.getIconUri();
+ if (uri == null) {
+ Slog.w(TAG, "null uri detected in getShortcutIconUri()");
+ return null;
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ int packageUid = mPackageManagerInternal.getPackageUidInternal(packageName,
+ PackageManager.MATCH_DIRECT_BOOT_AUTO, userId);
+ // Grant read uri permission to the caller on behalf of the shortcut owner. All
+ // granted permissions are revoked when the default launcher changes, or when
+ // device is rebooted.
+ // b/151572645 is tracking a bug where Uri permissions are persisted across
+ // reboots, even when Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION is not used.
+ mUriGrantsManager.grantUriPermissionFromOwner(mUriPermissionOwner, packageUid,
+ launcherPackage, Uri.parse(uri), Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ userId, launcherUserId);
+ } catch (Exception e) {
+ Slog.e(TAG, "Failed to grant uri access to " + launcherPackage + " for " + uri,
+ e);
+ uri = null;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return uri;
+ }
+ }
+
+ @Override
public boolean hasShortcutHostPermission(int launcherUserId,
@NonNull String callingPackage, int callingPid, int callingUid) {
return ShortcutService.this.hasShortcutHostPermission(callingPackage, launcherUserId,
@@ -3241,7 +3315,14 @@
user.clearLauncher();
}
if (Intent.ACTION_PREFERRED_ACTIVITY_CHANGED.equals(action)) {
- // Nothing farther to do.
+ final ShortcutUser user = getUserShortcutsLocked(userId);
+ final ComponentName lastLauncher = user.getLastKnownLauncher();
+ final ComponentName currentLauncher = getDefaultLauncher(userId);
+ if (currentLauncher == null || !currentLauncher.equals(lastLauncher)) {
+ // Default launcher is removed or changed, revoke all URI permissions.
+ mUriGrantsManagerInternal.revokeUriPermissionFromOwner(mUriPermissionOwner,
+ null, ~0, 0);
+ }
return;
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 1c2fcc1..8280a61 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -455,11 +455,13 @@
@Override
public void onFinished(int id, Bundle extras) {
- try {
- mContext.startIntentSender(mTarget, null, 0, 0, 0);
- } catch (IntentSender.SendIntentException e) {
- Slog.e(LOG_TAG, "Failed to start the target in the callback", e);
- }
+ mHandler.post(() -> {
+ try {
+ mContext.startIntentSender(mTarget, null, 0, 0, 0);
+ } catch (IntentSender.SendIntentException e) {
+ Slog.e(LOG_TAG, "Failed to start the target in the callback", e);
+ }
+ });
}
}
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index f8e5082..1d7d038 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -277,9 +277,6 @@
public boolean isAppPredictor() {
return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0;
}
- public boolean isTelephony() {
- return (protectionLevel & PermissionInfo.PROTECTION_FLAG_TELEPHONY) != 0;
- }
public boolean isCompanion() {
return (protectionLevel & PermissionInfo.PROTECTION_FLAG_COMPANION) != 0;
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 46f121d..5d6eaf2 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -3464,13 +3464,6 @@
// Special permissions for the system app predictor.
allowed = true;
}
- if (!allowed && bp.isTelephony()
- && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_TELEPHONY, UserHandle.USER_SYSTEM),
- pkg.getPackageName())) {
- // Special permissions for the system telephony apps.
- allowed = true;
- }
if (!allowed && bp.isCompanion()
&& ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
PackageManagerInternal.PACKAGE_COMPANION, UserHandle.USER_SYSTEM),
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 294deba..3257b63 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -18,6 +18,8 @@
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT;
+import static android.os.PowerManagerInternal.MODE_DEVICE_IDLE;
+import static android.os.PowerManagerInternal.MODE_DISPLAY_INACTIVE;
import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
@@ -42,8 +44,6 @@
import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
-import android.hardware.power.Boost;
-import android.hardware.power.Mode;
import android.hardware.power.V1_0.PowerHint;
import android.net.Uri;
import android.os.BatteryManager;
@@ -2975,6 +2975,8 @@
synchronized (mLock) {
if (mDisplayState != state) {
mDisplayState = state;
+ setPowerModeInternal(MODE_DISPLAY_INACTIVE,
+ !Display.isActiveState(state));
if (state == Display.STATE_OFF) {
if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
setHalInteractiveModeLocked(false);
@@ -3297,6 +3299,7 @@
}
mDeviceIdleMode = enabled;
updateWakeLockDisabledStatesLocked();
+ setPowerModeInternal(MODE_DEVICE_IDLE, mDeviceIdleMode || mLightDeviceIdleMode);
}
if (enabled) {
EventLogTags.writeDeviceIdleOnPhase("power");
@@ -3310,6 +3313,7 @@
synchronized (mLock) {
if (mLightDeviceIdleMode != enabled) {
mLightDeviceIdleMode = enabled;
+ setPowerModeInternal(MODE_DEVICE_IDLE, mDeviceIdleMode || mLightDeviceIdleMode);
return true;
}
return false;
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
index 1292f6c..63048f6 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareValidation.java
@@ -252,8 +252,21 @@
* @param permission The permission to check.
*/
void enforcePermission(String permission) {
- mContext.enforceCallingOrSelfPermission(permission,
- String.format("Caller must have the %s permission.", permission));
+ final int status = PermissionChecker.checkCallingOrSelfPermissionForPreflight(mContext,
+ permission);
+ switch (status) {
+ case PermissionChecker.PERMISSION_GRANTED:
+ return;
+ case PermissionChecker.PERMISSION_HARD_DENIED:
+ throw new SecurityException(
+ String.format("Caller must have the %s permission.", permission));
+ case PermissionChecker.PERMISSION_SOFT_DENIED:
+ throw new ServiceSpecificException(Status.TEMPORARY_PERMISSION_DENIED,
+ String.format("Caller must have the %s permission.", permission));
+ default:
+ throw new InternalServerError(
+ new RuntimeException("Unexpected perimission check result."));
+ }
}
@Override
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index fd275d8..f1f5bfe 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -1292,7 +1292,7 @@
int pullSystemUptime(int atomTag, List<StatsEvent> pulledData) {
StatsEvent e = StatsEvent.newBuilder()
.setAtomId(atomTag)
- .writeLong(SystemClock.elapsedRealtime())
+ .writeLong(SystemClock.uptimeMillis())
.build();
pulledData.add(e);
return StatsManager.PULL_SUCCESS;
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 74a6383..0d16fcc 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -234,7 +234,7 @@
handleRequest(
event.getSystemTextClassifierMetadata(),
- /* verifyCallingPackage= */ false,
+ /* verifyCallingPackage= */ true,
/* attemptToBind= */ false,
service -> service.onSelectionEvent(sessionId, event),
"onSelectionEvent",
@@ -253,7 +253,7 @@
handleRequest(
systemTcMetadata,
- /* verifyCallingPackage= */ false,
+ /* verifyCallingPackage= */ true,
/* attemptToBind= */ false,
service -> service.onTextClassifierEvent(sessionId, event),
"onTextClassifierEvent",
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index 57b6ec9..fc52584 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -25,6 +25,8 @@
import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
import android.provider.Settings;
import com.android.internal.annotations.VisibleForTesting;
@@ -133,5 +135,13 @@
android.Manifest.permission.SUGGEST_MANUAL_TIME_AND_ZONE,
"suggest manual time and time zone");
}
+
+ @Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out,
+ FileDescriptor err, String[] args, ShellCallback callback,
+ ResultReceiver resultReceiver) {
+ (new TimeZoneDetectorShellCommand(this)).exec(
+ this, in, out, err, args, callback, resultReceiver);
+ }
}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
new file mode 100644
index 0000000..b051bab
--- /dev/null
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
@@ -0,0 +1,118 @@
+/*
+ * 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.server.timezonedetector;
+
+import android.app.timezonedetector.ManualTimeZoneSuggestion;
+import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
+import android.os.ShellCommand;
+
+import java.io.PrintWriter;
+
+/** Implemented the shell command interface for {@link TimeZoneDetectorService}. */
+class TimeZoneDetectorShellCommand extends ShellCommand {
+
+ private final TimeZoneDetectorService mInterface;
+
+ TimeZoneDetectorShellCommand(TimeZoneDetectorService timeZoneDetectorService) {
+ mInterface = timeZoneDetectorService;
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+
+ switch (cmd) {
+ case "suggestTelephonyTimeZone":
+ return runSuggestTelephonyTimeZone();
+ case "suggestManualTimeZone":
+ return runSuggestManualTimeZone();
+ default: {
+ return handleDefaultCommands(cmd);
+ }
+ }
+ }
+
+ private int runSuggestTelephonyTimeZone() {
+ final PrintWriter pw = getOutPrintWriter();
+ try {
+ TelephonyTimeZoneSuggestion suggestion = null;
+ String opt;
+ while ((opt = getNextArg()) != null) {
+ if ("--suggestion".equals(opt)) {
+ suggestion = TelephonyTimeZoneSuggestion.parseCommandLineArg(this);
+ } else {
+ pw.println("Error: Unknown option: " + opt);
+ return 1;
+ }
+ }
+ if (suggestion == null) {
+ pw.println("Error: suggestion not specified");
+ return 1;
+ }
+ mInterface.suggestTelephonyTimeZone(suggestion);
+ pw.println("Suggestion " + suggestion + " injected.");
+ return 0;
+ } catch (RuntimeException e) {
+ pw.println(e.toString());
+ return 1;
+ }
+ }
+
+ private int runSuggestManualTimeZone() {
+ final PrintWriter pw = getOutPrintWriter();
+ try {
+ ManualTimeZoneSuggestion suggestion = null;
+ String opt;
+ while ((opt = getNextArg()) != null) {
+ if ("--suggestion".equals(opt)) {
+ suggestion = ManualTimeZoneSuggestion.parseCommandLineArg(this);
+ } else {
+ pw.println("Error: Unknown option: " + opt);
+ return 1;
+ }
+ }
+ if (suggestion == null) {
+ pw.println("Error: suggestion not specified");
+ return 1;
+ }
+ mInterface.suggestManualTimeZone(suggestion);
+ pw.println("Suggestion " + suggestion + " injected.");
+ return 0;
+ } catch (RuntimeException e) {
+ pw.println(e.toString());
+ return 1;
+ }
+ }
+
+ @Override
+ public void onHelp() {
+ final PrintWriter pw = getOutPrintWriter();
+ pw.println("Time Zone Detector (time_zone_detector) commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println(" suggestTelephonyTimeZone");
+ pw.println(" --suggestion <telephony suggestion opts>");
+ pw.println(" suggestManualTimeZone");
+ pw.println(" --suggestion <manual suggestion opts>");
+ pw.println();
+ ManualTimeZoneSuggestion.printCommandLineOpts(pw);
+ pw.println();
+ TelephonyTimeZoneSuggestion.printCommandLineOpts(pw);
+ pw.println();
+ }
+}
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
index bd63b2d..7047a9e 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
@@ -16,7 +16,6 @@
package com.android.server.tv.tunerresourcemanager;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -41,8 +40,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.SystemService;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -79,25 +76,6 @@
// Used to synchronize the access to the service.
private final Object mLock = new Object();
- /**
- * Tuner resource type to help generate resource handle
- */
- @IntDef({
- TUNER_RESOURCE_TYPE_FRONTEND,
- TUNER_RESOURCE_TYPE_DEMUX,
- TUNER_RESOURCE_TYPE_DESCRAMBLER,
- TUNER_RESOURCE_TYPE_LNB,
- TUNER_RESOURCE_TYPE_CAS_SESSION,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TunerResourceType {}
-
- public static final int TUNER_RESOURCE_TYPE_FRONTEND = 0;
- public static final int TUNER_RESOURCE_TYPE_DEMUX = 1;
- public static final int TUNER_RESOURCE_TYPE_DESCRAMBLER = 2;
- public static final int TUNER_RESOURCE_TYPE_LNB = 3;
- public static final int TUNER_RESOURCE_TYPE_CAS_SESSION = 4;
-
public TunerResourceManagerService(@Nullable Context context) {
super(context);
}
@@ -122,6 +100,7 @@
@NonNull IResourcesReclaimListener listener, @NonNull int[] clientId)
throws RemoteException {
enforceTrmAccessPermission("registerClientProfile");
+ enforceTunerAccessPermission("registerClientProfile");
if (profile == null) {
throw new RemoteException("ResourceClientProfile can't be null");
}
@@ -465,7 +444,7 @@
// Grant frontend when there is unused resource.
if (grantingFrontendId > -1) {
frontendHandle[0] = generateResourceHandle(
- TUNER_RESOURCE_TYPE_FRONTEND, grantingFrontendId);
+ TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND, grantingFrontendId);
updateFrontendClientMappingOnNewGrant(grantingFrontendId, request.getClientId());
return true;
}
@@ -474,7 +453,7 @@
// request client has higher priority.
if (inUseLowestPriorityFrId > -1 && (requestClient.getPriority() > currentLowestPriority)) {
frontendHandle[0] = generateResourceHandle(
- TUNER_RESOURCE_TYPE_FRONTEND, inUseLowestPriorityFrId);
+ TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND, inUseLowestPriorityFrId);
reclaimFrontendResource(getFrontendResource(
inUseLowestPriorityFrId).getOwnerClientId());
updateFrontendClientMappingOnNewGrant(inUseLowestPriorityFrId, request.getClientId());
@@ -489,7 +468,7 @@
if (DEBUG) {
Slog.d(TAG, "requestDemux(request=" + request + ")");
}
- demuxHandle[0] = generateResourceHandle(TUNER_RESOURCE_TYPE_DEMUX, 0);
+ demuxHandle[0] = generateResourceHandle(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX, 0);
return true;
}
@@ -498,7 +477,8 @@
if (DEBUG) {
Slog.d(TAG, "requestDescrambler(request=" + request + ")");
}
- descramblerHandle[0] = generateResourceHandle(TUNER_RESOURCE_TYPE_DESCRAMBLER, 0);
+ descramblerHandle[0] =
+ generateResourceHandle(TunerResourceManager.TUNER_RESOURCE_TYPE_DESCRAMBLER, 0);
return true;
}
@@ -664,7 +644,8 @@
return mClientProfiles.keySet().contains(clientId);
}
- private int generateResourceHandle(@TunerResourceType int resourceType, int resourceId) {
+ private int generateResourceHandle(
+ @TunerResourceManager.TunerResourceType int resourceType, int resourceId) {
return (resourceType & 0x000000ff) << 24
| (resourceId << 16)
| (mResourceRequestCount++ & 0xffff);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index c4545fa..00c6f3a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -5936,7 +5936,7 @@
if (win == null) {
return;
}
- final Rect frame = win.getFrameLw();
+ final Rect frame = win.getRelativeFrameLw();
final int thumbnailDrawableRes = task.mUserId == mWmService.mCurrentUserId
? R.drawable.ic_account_circle
: R.drawable.ic_corp_badge;
@@ -5946,12 +5946,12 @@
if (thumbnail == null) {
return;
}
- final Transaction transaction = getAnimatingContainer().getPendingTransaction();
+ final Transaction transaction = getPendingTransaction();
mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
- transaction, getAnimatingContainer(), thumbnail);
+ transaction, getTask(), thumbnail);
final Animation animation =
getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
- win.getFrameLw());
+ frame);
mThumbnail.startAnimation(transaction, animation, new Point(frame.left, frame.top));
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 4ebb423..e8bfe8e 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -1510,7 +1510,7 @@
*/
@StackVisibility
int getVisibility(ActivityRecord starting) {
- if (!isAttached() || mForceHidden) {
+ if (!isAttached() || isForceHidden()) {
return STACK_VISIBILITY_INVISIBLE;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 6d7f8fb..57f357d 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -75,6 +75,7 @@
import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
import static com.android.server.wm.RootWindowContainer.TAG_STATES;
+import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_WHITELISTED;
@@ -1565,9 +1566,9 @@
* stopping list by handling the idle.
*/
stack.cancelAnimation();
- stack.mForceHidden = true;
+ stack.setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, true /* set */);
stack.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
- stack.mForceHidden = false;
+ stack.setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, false /* set */);
activityIdleInternal(null /* idleActivity */, false /* fromTimeout */,
true /* processPausingActivities */, null /* configuration */);
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index 1009771..57b6024 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -178,7 +178,7 @@
// before issuing the work challenge.
return true;
}
- return interceptWorkProfileChallengeIfNeeded();
+ return interceptLockedManagedProfileIfNeeded();
}
private boolean hasCrossProfileAnimation() {
@@ -296,7 +296,7 @@
return true;
}
- private boolean interceptWorkProfileChallengeIfNeeded() {
+ private boolean interceptLockedManagedProfileIfNeeded() {
final Intent interceptingIntent = interceptWithConfirmCredentialsIfNeeded(mAInfo, mUserId);
if (interceptingIntent == null) {
return false;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index c7a1391..14ca7cb 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -27,8 +27,10 @@
import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WaitResult.LAUNCH_STATE_COLD;
import static android.app.WaitResult.LAUNCH_STATE_HOT;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -167,6 +169,8 @@
// The display to launch the activity onto, barring any strong reason to do otherwise.
private int mPreferredDisplayId;
+ // The windowing mode to apply to the root task, if possible
+ private int mPreferredWindowingMode;
private Task mInTask;
@VisibleForTesting
@@ -538,6 +542,7 @@
mStartFlags = starter.mStartFlags;
mSourceRecord = starter.mSourceRecord;
mPreferredDisplayId = starter.mPreferredDisplayId;
+ mPreferredWindowingMode = starter.mPreferredWindowingMode;
mInTask = starter.mInTask;
mAddingToTask = starter.mAddingToTask;
@@ -1493,8 +1498,6 @@
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor, restrictedBgActivity);
- final int preferredWindowingMode = mLaunchParams.mWindowingMode;
-
computeLaunchingTaskFlags();
computeSourceStack();
@@ -1564,6 +1567,14 @@
if (!mAvoidMoveToFront && mDoResume) {
mTargetStack.moveToFront("reuseOrNewTask");
+ if (mOptions != null) {
+ if (mPreferredWindowingMode != WINDOWING_MODE_UNDEFINED) {
+ mTargetStack.setWindowingMode(mPreferredWindowingMode);
+ }
+ if (mOptions.getTaskAlwaysOnTop()) {
+ mTargetStack.setAlwaysOnTop(true);
+ }
+ }
}
mService.mUgmInternal.grantUriPermissionFromIntent(mCallingUid, mStartActivity.packageName,
@@ -1627,7 +1638,7 @@
// Update the recent tasks list immediately when the activity starts
mSupervisor.mRecentTasks.add(mStartActivity.getTask());
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
- preferredWindowingMode, mPreferredDisplayId, mTargetStack);
+ mPreferredWindowingMode, mPreferredDisplayId, mTargetStack);
return START_SUCCESS;
}
@@ -1680,9 +1691,10 @@
mSupervisor.getLaunchParamsController().calculate(targetTask, r.info.windowLayout, r,
sourceRecord, mOptions, PHASE_BOUNDS, mLaunchParams);
- mPreferredDisplayId =
- mLaunchParams.hasPreferredDisplay() ? mLaunchParams.mPreferredDisplayId
- : DEFAULT_DISPLAY;
+ mPreferredDisplayId = mLaunchParams.hasPreferredDisplay()
+ ? mLaunchParams.mPreferredDisplayId
+ : DEFAULT_DISPLAY;
+ mPreferredWindowingMode = mLaunchParams.mWindowingMode;
}
private int isAllowedToStart(ActivityRecord r, boolean newTask, Task targetTask) {
@@ -2006,6 +2018,7 @@
mStartFlags = 0;
mSourceRecord = null;
mPreferredDisplayId = INVALID_DISPLAY;
+ mPreferredWindowingMode = WINDOWING_MODE_UNDEFINED;
mInTask = null;
mAddingToTask = false;
@@ -2054,9 +2067,10 @@
// after we located a reusable task (which might be resided in another display).
mSupervisor.getLaunchParamsController().calculate(inTask, r.info.windowLayout, r,
sourceRecord, options, PHASE_DISPLAY, mLaunchParams);
- mPreferredDisplayId =
- mLaunchParams.hasPreferredDisplay() ? mLaunchParams.mPreferredDisplayId
- : DEFAULT_DISPLAY;
+ mPreferredDisplayId = mLaunchParams.hasPreferredDisplay()
+ ? mLaunchParams.mPreferredDisplayId
+ : DEFAULT_DISPLAY;
+ mPreferredWindowingMode = mLaunchParams.mWindowingMode;
mLaunchMode = r.launchMode;
@@ -2098,7 +2112,7 @@
}
if (mOptions != null) {
- if (mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
+ if (mOptions.getLaunchTaskId() != INVALID_TASK_ID && mOptions.getTaskOverlay()) {
r.setTaskOverlay(true);
if (!mOptions.canTaskOverlayResume()) {
final Task task = mRootWindowContainer.anyTaskForId(
@@ -2291,6 +2305,15 @@
* if not or an ActivityRecord with the task into which the new activity should be added.
*/
private Task getReusableTask() {
+ // If a target task is specified, try to reuse that one
+ if (mOptions != null && mOptions.getLaunchTaskId() != INVALID_TASK_ID) {
+ Task launchTask = mRootWindowContainer.anyTaskForId(mOptions.getLaunchTaskId());
+ if (launchTask != null) {
+ return launchTask;
+ }
+ return null;
+ }
+
// We may want to try to place the new activity in to an existing task. We always
// do this if the target activity is singleTask or singleInstance; we will also do
// this if NEW_TASK has been requested, and there is not an additional qualifier telling
@@ -2304,12 +2327,7 @@
// same component, then instead of launching bring that one to the front.
putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
ActivityRecord intentActivity = null;
- if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
- Task launchTask = mRootWindowContainer.anyTaskForId(mOptions.getLaunchTaskId());
- if (launchTask != null) {
- return launchTask;
- }
- } else if (putIntoExistingTask) {
+ if (putIntoExistingTask) {
if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
// There can be one and only one instance of single instance activity in the
// history, and it is always in its own unique task, so we do a special search.
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index ab96c61..38a406e 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -28,6 +28,7 @@
import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES;
import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
+import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
@@ -1024,6 +1025,13 @@
case TYPE_STATUS_BAR_PANEL:
return WindowManagerGlobal.ADD_INVALID_TYPE;
}
+
+ if (attrs.providesInsetsTypes != null) {
+ mContext.enforcePermission(
+ android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
+ "DisplayPolicy");
+ enforceSingleInsetsTypeCorrespondingToWindowType(attrs.providesInsetsTypes);
+ }
return ADD_OKAY;
}
@@ -1110,6 +1118,28 @@
});
if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
break;
+ default:
+ if (attrs.providesInsetsTypes != null) {
+ for (int insetsType : attrs.providesInsetsTypes) {
+ mDisplayContent.setInsetProvider(insetsType, win, null);
+ }
+ }
+ break;
+ }
+ }
+
+ private static void enforceSingleInsetsTypeCorrespondingToWindowType(int[] insetsTypes) {
+ int count = 0;
+ for (int insetsType : insetsTypes) {
+ switch (insetsType) {
+ case ITYPE_NAVIGATION_BAR:
+ case ITYPE_STATUS_BAR:
+ case ITYPE_CAPTION_BAR:
+ if (++count > 1) {
+ throw new IllegalArgumentException(
+ "Multiple InsetsTypes corresponding to Window type");
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index ee36db9..a4bdfb3 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
@@ -87,7 +88,8 @@
final InsetsSourceProvider provider = target.getControllableInsetProvider();
final @InternalInsetsType int type = provider != null
? provider.getSource().getType() : ITYPE_INVALID;
- return getInsetsForTypeAndWindowingMode(type, target.getWindowingMode());
+ return getInsetsForTypeAndWindowingMode(type, target.getWindowingMode(),
+ target.isAlwaysOnTop());
}
InsetsState getInsetsForWindowMetrics(@NonNull WindowManager.LayoutParams attrs) {
@@ -95,7 +97,9 @@
final WindowToken token = mDisplayContent.getWindowToken(attrs.token);
final @WindowingMode int windowingMode = token != null
? token.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
- return getInsetsForTypeAndWindowingMode(type, windowingMode);
+ final boolean alwaysOnTop = token != null
+ ? token.isAlwaysOnTop() : false;
+ return getInsetsForTypeAndWindowingMode(type, windowingMode, alwaysOnTop);
}
private static @InternalInsetsType int getInsetsTypeForWindowType(int type) {
@@ -113,7 +117,7 @@
/** @see #getInsetsForDispatch */
private InsetsState getInsetsForTypeAndWindowingMode(@InternalInsetsType int type,
- @WindowingMode int windowingMode) {
+ @WindowingMode int windowingMode, boolean isAlwaysOnTop) {
InsetsState state = mState;
if (type != ITYPE_INVALID) {
@@ -147,7 +151,8 @@
}
}
- if (WindowConfiguration.isFloating(windowingMode)) {
+ if (WindowConfiguration.isFloating(windowingMode)
+ || (windowingMode == WINDOWING_MODE_MULTI_WINDOW && isAlwaysOnTop)) {
state = new InsetsState(state);
state.removeSource(ITYPE_STATUS_BAR);
state.removeSource(ITYPE_NAVIGATION_BAR);
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 19f8ca9..aa817fd 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -36,6 +36,7 @@
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.function.Supplier;
/**
* A class that can run animations on objects that have a set of child surfaces. We do this by
@@ -145,7 +146,7 @@
if (mLeash == null) {
mLeash = createAnimationLeash(mAnimatable, surface, t, type,
mAnimatable.getSurfaceWidth(), mAnimatable.getSurfaceHeight(), 0 /* x */,
- 0 /* y */, hidden);
+ 0 /* y */, hidden, mService.mTransactionFactory);
mAnimatable.onAnimationLeashCreated(t, mLeash);
}
mAnimatable.onLeashAnimationStarting(t, mLeash);
@@ -374,13 +375,21 @@
static SurfaceControl createAnimationLeash(Animatable animatable, SurfaceControl surface,
Transaction t, @AnimationType int type, int width, int height, int x, int y,
- boolean hidden) {
+ boolean hidden, Supplier<Transaction> transactionFactory) {
if (DEBUG_ANIM) Slog.i(TAG, "Reparenting to leash");
final SurfaceControl.Builder builder = animatable.makeAnimationLeash()
.setParent(animatable.getAnimationLeashParent())
- .setHidden(hidden)
.setName(surface + " - animation-leash");
final SurfaceControl leash = builder.build();
+ if (!hidden) {
+ // TODO(b/151665759) Defer reparent calls
+ // We want the leash to be visible immediately but we want to set the effects on
+ // the layer. Since the transaction used in this function may be deferred, we apply
+ // another transaction immediately with the correct visibility and effects.
+ // If this doesn't work, you will can see the 2/3 button nav bar flicker during
+ // seamless rotation.
+ transactionFactory.get().unsetColor(leash).show(leash).apply();
+ }
t.setWindowCrop(leash, width, height);
t.setPosition(leash, x, y);
t.show(leash);
diff --git a/services/core/java/com/android/server/wm/SurfaceFreezer.java b/services/core/java/com/android/server/wm/SurfaceFreezer.java
index a696daf..8ab5043 100644
--- a/services/core/java/com/android/server/wm/SurfaceFreezer.java
+++ b/services/core/java/com/android/server/wm/SurfaceFreezer.java
@@ -75,7 +75,8 @@
mLeash = SurfaceAnimator.createAnimationLeash(mAnimatable, mAnimatable.getSurfaceControl(),
t, ANIMATION_TYPE_SCREEN_ROTATION, startBounds.width(), startBounds.height(),
- startBounds.left, startBounds.top, false /* hidden */);
+ startBounds.left, startBounds.top, false /* hidden */,
+ mWmService.mTransactionFactory);
mAnimatable.onAnimationLeashCreated(t, mLeash);
SurfaceControl freezeTarget = mAnimatable.getFreezeSnapshotTarget();
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index e78f2ee..f826deb 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -431,7 +431,10 @@
private boolean mForceShowForAllUsers;
/** When set, will force the task to report as invisible. */
- boolean mForceHidden = false;
+ static final int FLAG_FORCE_HIDDEN_FOR_PINNED_TASK = 1;
+ static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1;
+ private int mForceHiddenFlags = 0;
+
SurfaceControl.Transaction mMainWindowSizeChangeTransaction;
@@ -3047,7 +3050,7 @@
*/
@VisibleForTesting
boolean isTranslucent(ActivityRecord starting) {
- if (!isAttached() || mForceHidden) {
+ if (!isAttached() || isForceHidden()) {
return true;
}
final PooledPredicate p = PooledLambda.obtainPredicate(Task::isOpaqueActivity,
@@ -4045,17 +4048,17 @@
return;
}
// Let the old organizer know it has lost control.
- if (mTaskOrganizer != null) {
- sendTaskVanished();
- }
+ sendTaskVanished();
mTaskOrganizer = organizer;
sendTaskAppeared();
+ onTaskOrganizerChanged();
}
// Called on Binder death.
void taskOrganizerDied() {
mTaskOrganizer = null;
mLastTaskOrganizerWindowingMode = -1;
+ onTaskOrganizerChanged();
}
/**
@@ -4090,6 +4093,14 @@
mLastTaskOrganizerWindowingMode = windowingMode;
}
+ private void onTaskOrganizerChanged() {
+ if (mTaskOrganizer == null) {
+ // If this task is no longer controlled by a task organizer, then reset the force hidden
+ // state
+ setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, false /* set */);
+ }
+ }
+
@Override
void setSurfaceControl(SurfaceControl sc) {
super.setSurfaceControl(sc);
@@ -4200,6 +4211,31 @@
c.recycle();
}
+ /**
+ * Sets/unsets the forced-hidden state flag for this task depending on {@param set}.
+ * @return Whether the force hidden state changed
+ */
+ boolean setForceHidden(int flags, boolean set) {
+ int newFlags = mForceHiddenFlags;
+ if (set) {
+ newFlags |= flags;
+ } else {
+ newFlags &= ~flags;
+ }
+ if (mForceHiddenFlags == newFlags) {
+ return false;
+ }
+ mForceHiddenFlags = newFlags;
+ return true;
+ }
+
+ /**
+ * Returns whether this task is currently forced to be hidden for any reason.
+ */
+ protected boolean isForceHidden() {
+ return mForceHiddenFlags != 0;
+ }
+
@Override
long getProtoFieldId() {
return TASK;
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 9cbc9ee..cc52cb4 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -23,6 +23,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -230,7 +231,8 @@
}
}
- void unregisterTaskOrganizer(ITaskOrganizer organizer) {
+ @Override
+ public void unregisterTaskOrganizer(ITaskOrganizer organizer) {
final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
state.unlinkDeath();
if (mTaskOrganizersForWindowingMode.get(state.mWindowingMode) == state) {
@@ -475,6 +477,7 @@
if (!(container instanceof Task)) {
throw new RuntimeException("Invalid token in task transaction");
}
+ final Task task = (Task) container;
// The "client"-facing API should prevent bad changes; however, just in case, sanitize
// masks here.
int configMask = change.getConfigSetMask();
@@ -498,6 +501,11 @@
effects |= TRANSACT_EFFECTS_LIFECYCLE;
}
}
+ if ((change.getChangeMask() & WindowContainerTransaction.Change.CHANGE_HIDDEN) != 0) {
+ if (task.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, change.getHidden())) {
+ effects |= TRANSACT_EFFECTS_LIFECYCLE;
+ }
+ }
return effects;
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index f83b052..0f5cafe 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -352,9 +352,19 @@
}
task.getBounds(mTmpRect);
mTmpRect.offsetTo(0, 0);
+
+ SurfaceControl[] excludeLayers;
+ final WindowState imeWindow = task.getDisplayContent().mInputMethodWindow;
+ if (imeWindow != null) {
+ excludeLayers = new SurfaceControl[1];
+ excludeLayers[0] = imeWindow.getSurfaceControl();
+ } else {
+ excludeLayers = new SurfaceControl[0];
+ }
final SurfaceControl.ScreenshotGraphicBuffer screenshotBuffer =
- SurfaceControl.captureLayers(
- task.getSurfaceControl(), mTmpRect, scaleFraction, pixelFormat);
+ SurfaceControl.captureLayersExcluding(
+ task.getSurfaceControl(), mTmpRect, scaleFraction,
+ pixelFormat, excludeLayers);
if (outTaskSize != null) {
outTaskSize.x = mTmpRect.width();
outTaskSize.y = mTmpRect.height();
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 164d3e0..45023ac 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -99,10 +99,10 @@
if (lowResTaskSnapshotScale > 0) {
mLowResScaleFactor = lowResTaskSnapshotScale / highResTaskSnapshotScale;
- setEnableLowResSnapshots(true);
+ mEnableLowResSnapshots = true;
} else {
mLowResScaleFactor = 0;
- setEnableLowResSnapshots(false);
+ mEnableLowResSnapshots = false;
}
mUse16BitFormat = service.mContext.getResources().getBoolean(
@@ -175,14 +175,6 @@
}
/**
- * Not to be used. Only here for testing.
- */
- @VisibleForTesting
- void setEnableLowResSnapshots(boolean enabled) {
- mEnableLowResSnapshots = enabled;
- }
-
- /**
* Return if task snapshots are stored in 16 bit pixel format.
*
* @return true if task snapshots are stored in 16 bit pixel format.
@@ -405,7 +397,7 @@
return false;
}
- if (!enableLowResSnapshots()) {
+ if (!mEnableLowResSnapshots) {
swBitmap.recycle();
return true;
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 9a92832..a1902bb 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -2476,9 +2476,12 @@
boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener,
int waitingId) {
- boolean willSync = false;
- if (!isVisible()) {
- return willSync;
+ boolean willSync = true;
+
+ // If we are invisible, no need to sync, likewise if we are already engaged in a sync,
+ // we can't support overlapping syncs on a single container yet.
+ if (!isVisible() || mWaitingListener != null) {
+ return false;
}
mUsingBLASTSyncTransaction = true;
diff --git a/services/core/java/com/android/server/wm/WindowContainerThumbnail.java b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java
index 90e3be7..a27a112 100644
--- a/services/core/java/com/android/server/wm/WindowContainerThumbnail.java
+++ b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java
@@ -97,7 +97,7 @@
// TODO: This should be attached as a child to the app token, once the thumbnail animations
// use relative coordinates. Once we start animating task we can also consider attaching
// this to the task.
- mSurfaceControl = mWindowContainer.makeSurface()
+ mSurfaceControl = mWindowContainer.makeChildSurface(mWindowContainer.getTopChild())
.setName("thumbnail anim: " + mWindowContainer.toString())
.setBufferSize(mWidth, mHeight)
.setFormat(PixelFormat.TRANSLUCENT)
@@ -209,7 +209,7 @@
@Override
public Builder makeAnimationLeash() {
- return mWindowContainer.makeSurface();
+ return mWindowContainer.makeChildSurface(mWindowContainer.getTopChild());
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1a77807..83fff28 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -882,7 +882,13 @@
FEATURE_FREEFORM_WINDOW_MANAGEMENT) || Settings.Global.getInt(
resolver, DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
- mAtmService.mSupportsFreeformWindowManagement = freeformWindowManagement;
+ if (mAtmService.mSupportsFreeformWindowManagement != freeformWindowManagement) {
+ mAtmService.mSupportsFreeformWindowManagement = freeformWindowManagement;
+ synchronized (mGlobalLock) {
+ // Notify the root window container that the display settings value may change.
+ mRoot.onSettingsRetrieved();
+ }
+ }
}
void updateForceResizableTasks() {
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 336934e..822f383 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1448,13 +1448,13 @@
SET(BasebandCn0DbHz, measurement_V2_1->basebandCN0DbHz);
- if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_RECEIVER_ISB) {
- SET(ReceiverInterSignalBiasNanos, measurement_V2_1->receiverInterSignalBiasNs);
+ if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_FULL_ISB) {
+ SET(FullInterSignalBiasNanos, measurement_V2_1->fullInterSignalBiasNs);
}
- if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_RECEIVER_ISB_UNCERTAINTY) {
- SET(ReceiverInterSignalBiasUncertaintyNanos,
- measurement_V2_1->receiverInterSignalBiasUncertaintyNs);
+ if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_FULL_ISB_UNCERTAINTY) {
+ SET(FullInterSignalBiasUncertaintyNanos,
+ measurement_V2_1->fullInterSignalBiasUncertaintyNs);
}
if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_SATELLITE_ISB) {
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 29b2cd6..5f0c8fe3 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -598,6 +598,9 @@
// IFS callbacks.
void onPendingReads(dataloader::PendingReads pendingReads) final {
std::lock_guard lock{mOutFdLock};
+ if (mOutFd < 0) {
+ return;
+ }
CHECK(mIfs);
for (auto&& pendingRead : pendingReads) {
const android::dataloader::FileId& fileId = pendingRead.id;
@@ -611,13 +614,9 @@
android::incfs::toString(fileId).c_str());
continue;
}
- if (mRequestedFiles.insert(fileIdx).second) {
- if (!sendRequest(mOutFd, PREFETCH, fileIdx, blockIdx)) {
- ALOGE("Failed to request prefetch for fileid=%s. Ignore.",
- android::incfs::toString(fileId).c_str());
- mRequestedFiles.erase(fileIdx);
- mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
- }
+ if (mRequestedFiles.insert(fileIdx).second &&
+ !sendRequest(mOutFd, PREFETCH, fileIdx, blockIdx)) {
+ mRequestedFiles.erase(fileIdx);
}
sendRequest(mOutFd, BLOCK_MISSING, fileIdx, blockIdx);
}
@@ -634,7 +633,7 @@
}
if (res < 0) {
ALOGE("Failed to poll. Abort.");
- mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
+ mStatusListener->reportStatus(DATA_LOADER_UNRECOVERABLE);
break;
}
if (res == mEventFd) {
@@ -644,7 +643,7 @@
}
if (!readChunk(inout, data)) {
ALOGE("Failed to read a message. Abort.");
- mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
+ mStatusListener->reportStatus(DATA_LOADER_UNRECOVERABLE);
break;
}
auto remainingData = std::span(data);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index fc9044a..6ab5303 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1076,6 +1076,7 @@
private static final String TAG_PROFILE_OFF_DEADLINE = "profile-off-deadline";
private static final String TAG_ALWAYS_ON_VPN_PACKAGE = "vpn-package";
private static final String TAG_ALWAYS_ON_VPN_LOCKDOWN = "vpn-lockdown";
+ private static final String TAG_COMMON_CRITERIA_MODE = "common-criteria-mode";
DeviceAdminInfo info;
@@ -1206,7 +1207,7 @@
public String mAlwaysOnVpnPackage;
public boolean mAlwaysOnVpnLockdown;
-
+ boolean mCommonCriteriaMode;
ActiveAdmin(DeviceAdminInfo _info, boolean parent) {
info = _info;
@@ -1454,6 +1455,9 @@
if (mAlwaysOnVpnLockdown) {
writeAttributeValueToXml(out, TAG_ALWAYS_ON_VPN_LOCKDOWN, mAlwaysOnVpnLockdown);
}
+ if (mCommonCriteriaMode) {
+ writeAttributeValueToXml(out, TAG_COMMON_CRITERIA_MODE, mCommonCriteriaMode);
+ }
}
void writeTextToXml(XmlSerializer out, String tag, String text) throws IOException {
@@ -1704,6 +1708,9 @@
} else if (TAG_ALWAYS_ON_VPN_LOCKDOWN.equals(tag)) {
mAlwaysOnVpnLockdown = Boolean.parseBoolean(
parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_COMMON_CRITERIA_MODE.equals(tag)) {
+ mCommonCriteriaMode = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
} else {
Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
XmlUtils.skipCurrentTag(parser);
@@ -1940,6 +1947,8 @@
pw.println(mAlwaysOnVpnPackage);
pw.print("mAlwaysOnVpnLockdown=");
pw.println(mAlwaysOnVpnLockdown);
+ pw.print("mCommonCriteriaMode=");
+ pw.println(mCommonCriteriaMode);
}
}
@@ -15606,28 +15615,38 @@
}
@Override
- public void setCommonCriteriaModeEnabled(ComponentName admin, boolean enabled) {
+ public void setCommonCriteriaModeEnabled(ComponentName who, boolean enabled) {
+ final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(admin,
+ final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER);
+ admin.mCommonCriteriaMode = enabled;
+ saveSettingsLocked(userId);
}
- mInjector.binderWithCleanCallingIdentity(
- () -> mInjector.settingsGlobalPutInt(Settings.Global.COMMON_CRITERIA_MODE,
- enabled ? 1 : 0));
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_COMMON_CRITERIA_MODE)
- .setAdmin(admin)
+ .setAdmin(who)
.setBoolean(enabled)
.write();
}
@Override
- public boolean isCommonCriteriaModeEnabled(ComponentName admin) {
- synchronized (getLockObject()) {
- getActiveAdminForCallerLocked(admin,
- DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER);
+ public boolean isCommonCriteriaModeEnabled(ComponentName who) {
+ if (who != null) {
+ synchronized (getLockObject()) {
+ final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER);
+ return admin.mCommonCriteriaMode;
+ }
}
- return mInjector.settingsGlobalGetInt(Settings.Global.COMMON_CRITERIA_MODE, 0) != 0;
+ // Return aggregated state if caller is not admin (who == null).
+ synchronized (getLockObject()) {
+ // Only DO or COPE PO can turn on CC mode, so take a shortcut here and only look at
+ // their ActiveAdmin, instead of iterating through all admins.
+ final ActiveAdmin admin = getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceLocked(
+ UserHandle.USER_SYSTEM);
+ return admin != null ? admin.mCommonCriteriaMode : false;
+ }
}
@Override
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 7275936..ed85b93 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -941,7 +941,7 @@
if (!dataloader) {
return false;
}
- status = dataloader->start();
+ status = dataloader->start(mountId);
if (!status.isOk()) {
return false;
}
@@ -1090,7 +1090,9 @@
base::unique_fd(::dup(ifs.control.pendingReads)));
fsControlParcel.incremental->log.reset(base::unique_fd(::dup(ifs.control.logs)));
sp<IncrementalDataLoaderListener> listener =
- new IncrementalDataLoaderListener(*this, *externalListener);
+ new IncrementalDataLoaderListener(*this,
+ externalListener ? *externalListener
+ : DataLoaderStatusListener());
bool created = false;
auto status = mDataLoaderManager->initializeDataLoader(ifs.mountId, *dlp, fsControlParcel,
listener, &created);
@@ -1168,6 +1170,10 @@
// If one lib file fails to be created, abort others as well
break;
}
+ // If it is a zero-byte file, skip data writing
+ if (uncompressedLen == 0) {
+ continue;
+ }
// Write extracted data to new file
std::vector<uint8_t> libData(uncompressedLen);
@@ -1230,8 +1236,8 @@
std::unique_lock l(incrementalService.mLock);
const auto& ifs = incrementalService.getIfsLocked(mountId);
if (!ifs) {
- LOG(WARNING) << "Received data loader status " << int(newStatus) << " for unknown mount "
- << mountId;
+ LOG(WARNING) << "Received data loader status " << int(newStatus)
+ << " for unknown mount " << mountId;
return binder::Status::ok();
}
ifs->dataLoaderStatus = newStatus;
@@ -1246,14 +1252,6 @@
}
switch (newStatus) {
- case IDataLoaderStatusListener::DATA_LOADER_NO_CONNECTION: {
- // TODO(b/150411019): handle data loader connection loss
- break;
- }
- case IDataLoaderStatusListener::DATA_LOADER_CONNECTION_OK: {
- // TODO(b/150411019): handle data loader connection loss
- break;
- }
case IDataLoaderStatusListener::DATA_LOADER_CREATED: {
if (startRequested) {
incrementalService.startDataLoader(mountId);
@@ -1275,6 +1273,10 @@
case IDataLoaderStatusListener::DATA_LOADER_IMAGE_NOT_READY: {
break;
}
+ case IDataLoaderStatusListener::DATA_LOADER_UNRECOVERABLE: {
+ // Nothing for now. Rely on externalListener to handle this.
+ break;
+ }
default: {
LOG(WARNING) << "Unknown data loader status: " << newStatus
<< " for mount: " << mountId;
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index 6002226..f5b88d9 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -100,10 +100,11 @@
const sp<IDataLoaderStatusListener>&) override {
return binder::Status::ok();
}
- binder::Status start() override { return binder::Status::ok(); }
- binder::Status stop() override { return binder::Status::ok(); }
- binder::Status destroy() override { return binder::Status::ok(); }
- binder::Status prepareImage(const std::vector<InstallationFileParcel>&,
+ binder::Status start(int32_t) override { return binder::Status::ok(); }
+ binder::Status stop(int32_t) override { return binder::Status::ok(); }
+ binder::Status destroy(int32_t) override { return binder::Status::ok(); }
+ binder::Status prepareImage(int32_t,
+ const std::vector<InstallationFileParcel>&,
const std::vector<std::string>&) override {
return binder::Status::ok();
}
diff --git a/services/robotests/backup/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java b/services/robotests/backup/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
index 84421ef..77b5b61 100644
--- a/services/robotests/backup/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
+++ b/services/robotests/backup/src/com/android/server/backup/testing/BackupManagerServiceTestUtils.java
@@ -166,7 +166,7 @@
PowerManager powerManager =
(PowerManager) application.getSystemService(Context.POWER_SERVICE);
return new UserBackupManagerService.BackupWakeLock(
- powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*"));
+ powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*"), 0);
}
/**
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
index efe8119..23381ff 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
@@ -46,6 +46,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManagerInternal;
import android.os.Debug;
+import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
@@ -55,6 +56,7 @@
import android.text.TextUtils;
import android.util.Pair;
+import com.android.internal.util.ArrayUtils;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.appop.AppOpsService;
@@ -71,10 +73,17 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Random;
+import java.util.zip.GZIPInputStream;
/**
* Test class for {@link android.app.ApplicationExitInfo}.
@@ -119,6 +128,8 @@
setFieldValue(AppExitInfoTracker.class, mAppExitInfoTracker, "mAppExitInfoSourceLmkd",
spy(mAppExitInfoTracker.new AppExitInfoExternalSource("lmkd",
ApplicationExitInfo.REASON_LOW_MEMORY)));
+ setFieldValue(AppExitInfoTracker.class, mAppExitInfoTracker, "mAppTraceRetriever",
+ spy(mAppExitInfoTracker.new AppTraceRetriever()));
setFieldValue(ProcessList.class, mProcessList, "mAppExitInfoTracker", mAppExitInfoTracker);
mInjector = new TestInjector(mContext);
mAms = new ActivityManagerService(mInjector, mServiceThreadRule.getThread());
@@ -169,6 +180,11 @@
public void testApplicationExitInfo() throws Exception {
mAppExitInfoTracker.clearProcessExitInfo(true);
mAppExitInfoTracker.mAppExitInfoLoaded = true;
+ mAppExitInfoTracker.mProcExitStoreDir = new File(mContext.getFilesDir(),
+ AppExitInfoTracker.APP_EXIT_STORE_DIR);
+ assertTrue(FileUtils.createDir(mAppExitInfoTracker.mProcExitStoreDir));
+ mAppExitInfoTracker.mProcExitInfoFile = new File(mAppExitInfoTracker.mProcExitStoreDir,
+ AppExitInfoTracker.APP_EXIT_INFO_FILE);
// Test application calls System.exit()
doNothing().when(mAppExitInfoTracker).schedulePersistProcessExitInfo(anyBoolean());
@@ -188,6 +204,10 @@
final long app1Rss3 = 45680;
final String app1ProcessName = "com.android.test.stub1:process";
final String app1PackageName = "com.android.test.stub1";
+ final byte[] app1Cookie1 = {(byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+ (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08};
+ final byte[] app1Cookie2 = {(byte) 0x08, (byte) 0x07, (byte) 0x06, (byte) 0x05,
+ (byte) 0x04, (byte) 0x03, (byte) 0x02, (byte) 0x01};
final long now1 = System.currentTimeMillis();
ProcessRecord app = makeProcessRecord(
@@ -204,6 +224,9 @@
// Case 1: basic System.exit() test
int exitCode = 5;
+ mAppExitInfoTracker.setProcessStateSummary(app1Uid, app1Pid1, app1Cookie1);
+ assertTrue(ArrayUtils.equals(mAppExitInfoTracker.getProcessStateSummary(app1Uid,
+ app1Pid1), app1Cookie1, app1Cookie1.length));
doReturn(new Pair<Long, Object>(now1, Integer.valueOf(makeExitStatus(exitCode))))
.when(mAppExitInfoTracker.mAppExitInfoSourceZygote)
.remove(anyInt(), anyInt());
@@ -235,6 +258,10 @@
IMPORTANCE_CACHED, // importance
null); // description
+ assertTrue(ArrayUtils.equals(info.getProcessStateSummary(), app1Cookie1,
+ app1Cookie1.length));
+ assertEquals(info.getTraceInputStream(), null);
+
// Case 2: create another app1 process record with a different pid
sleep(1);
final long now2 = System.currentTimeMillis();
@@ -250,6 +277,12 @@
app1ProcessName, // processName
app1PackageName); // packageName
exitCode = 6;
+
+ mAppExitInfoTracker.setProcessStateSummary(app1Uid, app1Pid2, app1Cookie1);
+ // Override with a different cookie
+ mAppExitInfoTracker.setProcessStateSummary(app1Uid, app1Pid2, app1Cookie2);
+ assertTrue(ArrayUtils.equals(mAppExitInfoTracker.getProcessStateSummary(app1Uid,
+ app1Pid2), app1Cookie2, app1Cookie2.length));
doReturn(new Pair<Long, Object>(now2, Integer.valueOf(makeExitStatus(exitCode))))
.when(mAppExitInfoTracker.mAppExitInfoSourceZygote)
.remove(anyInt(), anyInt());
@@ -280,6 +313,12 @@
IMPORTANCE_SERVICE, // importance
null); // description
+ assertTrue(ArrayUtils.equals(info.getProcessStateSummary(), app1Cookie2,
+ app1Cookie2.length));
+ info = list.get(1);
+ assertTrue(ArrayUtils.equals(info.getProcessStateSummary(), app1Cookie1,
+ app1Cookie1.length));
+
// Case 3: Create an instance of app1 with different user, and died because of SIGKILL
sleep(1);
final long now3 = System.currentTimeMillis();
@@ -702,9 +741,19 @@
app1PackageName); // packageName
mAppExitInfoTracker.mIsolatedUidRecords.addIsolatedUid(app1IsolatedUid2User2, app1UidUser2);
+
+ // Pretent it gets an ANR trace too (although the reason here should be REASON_ANR)
+ final File traceFile = new File(mContext.getFilesDir(), "anr_original.txt");
+ final int traceSize = 10240;
+ final int traceStart = 1024;
+ final int traceEnd = 8192;
+ createRandomFile(traceFile, traceSize);
+ assertEquals(traceSize, traceFile.length());
+ mAppExitInfoTracker.handleLogAnrTrace(app.pid, app.uid, app.getPackageList(),
+ traceFile, traceStart, traceEnd);
+
noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_TOO_MANY_EMPTY, app1Description2);
-
updateExitInfo(app);
list.clear();
mAppExitInfoTracker.getExitInfo(app1PackageName, app1UidUser2, app1Pid2User2, 1, list);
@@ -729,6 +778,10 @@
IMPORTANCE_CACHED, // importance
app1Description2); // description
+ // Verify if the traceFile get copied into the records correctly.
+ verifyTraceFile(traceFile, traceStart, info.getTraceFile(), 0, traceEnd - traceStart);
+ traceFile.delete();
+ info.getTraceFile().delete();
// Case 9: User2 gets removed
sleep(1);
@@ -801,8 +854,6 @@
mAppExitInfoTracker.getExitInfo(null, app1Uid, 0, 0, original);
assertTrue(original.size() > 0);
- mAppExitInfoTracker.mProcExitInfoFile = new File(mContext.getFilesDir(),
- AppExitInfoTracker.APP_EXIT_INFO_FILE);
mAppExitInfoTracker.persistProcessExitInfo();
assertTrue(mAppExitInfoTracker.mProcExitInfoFile.exists());
@@ -836,6 +887,37 @@
}
}
+ private static void createRandomFile(File file, int size) throws IOException {
+ try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
+ Random random = new Random();
+ byte[] buf = random.ints('a', 'z').limit(size).collect(
+ StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
+ .toString().getBytes();
+ out.write(buf);
+ }
+ }
+
+ private static void verifyTraceFile(File originFile, int originStart, File traceFile,
+ int traceStart, int length) throws IOException {
+ assertTrue(originFile.exists());
+ assertTrue(traceFile.exists());
+ assertTrue(originStart < originFile.length());
+ try (GZIPInputStream traceIn = new GZIPInputStream(new FileInputStream(traceFile));
+ BufferedInputStream originIn = new BufferedInputStream(
+ new FileInputStream(originFile))) {
+ assertEquals(traceStart, traceIn.skip(traceStart));
+ assertEquals(originStart, originIn.skip(originStart));
+ byte[] buf1 = new byte[8192];
+ byte[] buf2 = new byte[8192];
+ while (length > 0) {
+ int len = traceIn.read(buf1, 0, Math.min(buf1.length, length));
+ assertEquals(len, originIn.read(buf2, 0, len));
+ assertTrue(ArrayUtils.equals(buf1, buf2, len));
+ length -= len;
+ }
+ }
+ }
+
private ProcessRecord makeProcessRecord(int pid, int uid, int packageUid, Integer definingUid,
int connectionGroup, int procState, long pss, long rss,
String processName, String packageName) {
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 d038d6c..f57b5f2 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -5990,26 +5990,29 @@
public void testSetCommonCriteriaMode_asDeviceOwner() throws Exception {
setDeviceOwner();
- dpm.setCommonCriteriaModeEnabled(admin1, true);
- verify(getServices().settings).settingsGlobalPutInt(
- Settings.Global.COMMON_CRITERIA_MODE, 1);
+ assertFalse(dpm.isCommonCriteriaModeEnabled(admin1));
+ assertFalse(dpm.isCommonCriteriaModeEnabled(null));
- when(getServices().settings.settingsGlobalGetInt(Settings.Global.COMMON_CRITERIA_MODE, 0))
- .thenReturn(1);
+ dpm.setCommonCriteriaModeEnabled(admin1, true);
+
assertTrue(dpm.isCommonCriteriaModeEnabled(admin1));
+ assertTrue(dpm.isCommonCriteriaModeEnabled(null));
}
public void testSetCommonCriteriaMode_asPoOfOrgOwnedDevice() throws Exception {
- setupProfileOwner();
- configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE);
+ final int managedProfileUserId = 15;
+ final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
+ addManagedProfile(admin1, managedProfileAdminUid, admin1);
+ configureProfileOwnerOfOrgOwnedDevice(admin1, managedProfileUserId);
+ mContext.binder.callingUid = managedProfileAdminUid;
+
+ assertFalse(dpm.isCommonCriteriaModeEnabled(admin1));
+ assertFalse(dpm.isCommonCriteriaModeEnabled(null));
dpm.setCommonCriteriaModeEnabled(admin1, true);
- verify(getServices().settings).settingsGlobalPutInt(
- Settings.Global.COMMON_CRITERIA_MODE, 1);
- when(getServices().settings.settingsGlobalGetInt(Settings.Global.COMMON_CRITERIA_MODE, 0))
- .thenReturn(1);
assertTrue(dpm.isCommonCriteriaModeEnabled(admin1));
+ assertTrue(dpm.isCommonCriteriaModeEnabled(null));
}
public void testCanProfileOwnerResetPasswordWhenLocked_nonDirectBootAwarePo()
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/FakeSettings.java b/services/tests/servicestests/src/com/android/server/locksettings/FakeSettings.java
index 70a927c..c5e924b 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/FakeSettings.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/FakeSettings.java
@@ -15,16 +15,23 @@
*/
package com.android.server.locksettings;
+import android.content.ContentResolver;
+import android.os.UserHandle;
import android.provider.Settings;
public class FakeSettings {
private int mDeviceProvisioned;
+ private int mSecureFrpMode;
public void setDeviceProvisioned(boolean provisioned) {
mDeviceProvisioned = provisioned ? 1 : 0;
}
+ public void setSecureFrpMode(boolean secure) {
+ mSecureFrpMode = secure ? 1 : 0;
+ }
+
public int globalGetInt(String keyName) {
switch (keyName) {
case Settings.Global.DEVICE_PROVISIONED:
@@ -33,4 +40,12 @@
throw new IllegalArgumentException("Unhandled global settings: " + keyName);
}
}
+
+ public int secureGetInt(ContentResolver contentResolver, String keyName, int defaultValue,
+ int userId) {
+ if (Settings.Secure.SECURE_FRP_MODE.equals(keyName) && userId == UserHandle.USER_SYSTEM) {
+ return mSecureFrpMode;
+ }
+ return defaultValue;
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 1ff451b..4e1454b 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -124,6 +124,12 @@
}
@Override
+ public int settingsSecureGetInt(ContentResolver contentResolver, String keyName,
+ int defaultValue, int userId) {
+ return mSettings.secureGetInt(contentResolver, keyName, defaultValue, userId);
+ }
+
+ @Override
public UserManagerInternal getUserManagerInternal() {
return mUserManagerInternal;
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
index 684bbd4..661ce11 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
@@ -416,6 +416,15 @@
eq(CREDENTIAL_TYPE_PASSWORD), any(), eq(MANAGED_PROFILE_USER_ID));
}
+ @Test
+ public void testCredentialChangeNotPossibleInSecureFrpMode() {
+ mSettings.setSecureFrpMode(true);
+ try {
+ mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID);
+ fail("Password shouldn't be changeable before FRP unlock");
+ } catch (SecurityException e) { }
+ }
+
private void testCreateCredential(int userId, LockscreenCredential credential)
throws RemoteException {
assertTrue(mService.setLockCredential(credential, nonePassword(), userId));
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 7e3cfc8..128177b 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -1084,7 +1084,7 @@
// pretend that 512 bytes total have happened
stats = new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
+ .insertEntry(TEST_IFACE, 256L, 2L, 256L, 2L);
when(mStatsService.getNetworkTotalBytes(sTemplateWifi, CYCLE_START, CYCLE_END))
.thenReturn(stats.getTotalBytes());
@@ -1276,11 +1276,11 @@
history.recordData(start, end,
new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1440), 0L, 0L, 0L, 0));
stats.clear();
- stats.addEntry(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
+ stats.insertEntry(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
- stats.addEntry(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
+ stats.insertEntry(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
- stats.addEntry(IFACE_ALL, UID_C, SET_ALL, TAG_ALL,
+ stats.insertEntry(IFACE_ALL, UID_C, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
reset(mNotifManager);
@@ -1304,9 +1304,9 @@
history.recordData(start, end,
new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1440), 0L, 0L, 0L, 0));
stats.clear();
- stats.addEntry(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
+ stats.insertEntry(IFACE_ALL, UID_A, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(960), 0, 0, 0, 0);
- stats.addEntry(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
+ stats.insertEntry(IFACE_ALL, UID_B, SET_ALL, TAG_ALL,
DataUnit.MEGABYTES.toBytes(480), 0, 0, 0, 0);
reset(mNotifManager);
@@ -1338,7 +1338,7 @@
// bring up wifi network with metered policy
state = new NetworkState[] { buildWifi() };
stats = new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 0L, 0L, 0L, 0L);
+ .insertEntry(TEST_IFACE, 0L, 0L, 0L, 0L);
{
when(mConnManager.getAllNetworkState()).thenReturn(state);
@@ -1769,7 +1769,7 @@
final int CYCLE_DAY = 15;
final NetworkStats stats = new NetworkStats(0L, 1);
- stats.addEntry(TEST_IFACE, UID_A, SET_ALL, TAG_NONE,
+ stats.insertEntry(TEST_IFACE, UID_A, SET_ALL, TAG_NONE,
2999, 1, 2000, 1, 0);
when(mStatsService.getNetworkTotalBytes(any(), anyLong(), anyLong()))
.thenReturn(stats.getTotalBytes());
@@ -1793,7 +1793,7 @@
reset(mStatsService);
// Increase the usage.
- stats.addEntry(TEST_IFACE, UID_A, SET_ALL, TAG_NONE,
+ stats.insertEntry(TEST_IFACE, UID_A, SET_ALL, TAG_NONE,
1000, 1, 999, 1, 0);
when(mStatsService.getNetworkTotalBytes(any(), anyLong(), anyLong()))
.thenReturn(stats.getTotalBytes());
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 5d5c714..22591c6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -31,6 +31,7 @@
import android.content.pm.Signature;
import android.content.pm.parsing.ParsingPackage;
import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedIntentInfo;
import android.content.pm.parsing.component.ParsedProvider;
import android.os.Build;
@@ -135,6 +136,13 @@
.addActivity(activity);
}
+ private static ParsingPackage pkgWithInstrumentation(
+ String packageName, String instrumentationTargetPackage) {
+ ParsedInstrumentation instrumentation = new ParsedInstrumentation();
+ instrumentation.setTargetPackage(instrumentationTargetPackage);
+ return pkg(packageName).addInstrumentation(instrumentation);
+ }
+
private static ParsingPackage pkgWithProvider(String packageName, String authority) {
ParsedProvider provider = new ParsedProvider();
provider.setPackageName(packageName);
@@ -608,6 +616,25 @@
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
}
+ @Test
+ public void testInstrumentation_DoesntFilter() {
+ final AppsFilter appsFilter =
+ new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ appsFilter.onSystemReady();
+
+
+ PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
+ DUMMY_TARGET_UID);
+ PackageSetting instrumentation = simulateAddPackage(appsFilter,
+ pkgWithInstrumentation("com.some.other.package", "com.some.package"),
+ DUMMY_CALLING_UID);
+
+ assertFalse(
+ appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, instrumentation, target, 0));
+ assertFalse(
+ appsFilter.shouldFilterApplication(DUMMY_TARGET_UID, target, instrumentation, 0));
+ }
+
private interface WithSettingBuilder {
PackageSettingBuilder withBuilder(PackageSettingBuilder builder);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 6c769485..6a88298 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -94,6 +94,8 @@
import com.android.server.SystemService;
import com.android.server.pm.LauncherAppsService.LauncherAppsImpl;
import com.android.server.pm.ShortcutUser.PackageWithUser;
+import com.android.server.uri.UriGrantsManagerInternal;
+import com.android.server.uri.UriPermissionOwner;
import com.android.server.wm.ActivityTaskManagerInternal;
import org.junit.Assert;
@@ -630,6 +632,9 @@
protected UsageStatsManagerInternal mMockUsageStatsManagerInternal;
protected ActivityManagerInternal mMockActivityManagerInternal;
protected ActivityTaskManagerInternal mMockActivityTaskManagerInternal;
+ protected UriGrantsManagerInternal mMockUriGrantsManagerInternal;
+
+ protected UriPermissionOwner mUriPermissionOwner;
protected static final String CALLING_PACKAGE_1 = "com.android.test.1";
protected static final int CALLING_UID_1 = 10001;
@@ -771,6 +776,7 @@
mMockUsageStatsManagerInternal = mock(UsageStatsManagerInternal.class);
mMockActivityManagerInternal = mock(ActivityManagerInternal.class);
mMockActivityTaskManagerInternal = mock(ActivityTaskManagerInternal.class);
+ mMockUriGrantsManagerInternal = mock(UriGrantsManagerInternal.class);
LocalServices.removeServiceForTest(PackageManagerInternal.class);
LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal);
@@ -782,6 +788,10 @@
LocalServices.addService(ActivityTaskManagerInternal.class, mMockActivityTaskManagerInternal);
LocalServices.removeServiceForTest(UserManagerInternal.class);
LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
+ LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
+ LocalServices.addService(UriGrantsManagerInternal.class, mMockUriGrantsManagerInternal);
+
+ mUriPermissionOwner = new UriPermissionOwner(mMockUriGrantsManagerInternal, TAG);
// Prepare injection values.
@@ -2193,6 +2203,7 @@
for (ShortcutInfo s : actualShortcuts) {
assertTrue("ID " + s.getId() + " not have icon res ID", s.hasIconResource());
assertFalse("ID " + s.getId() + " shouldn't have icon FD", s.hasIconFile());
+ assertFalse("ID " + s.getId() + " shouldn't have icon URI", s.hasIconUri());
}
return actualShortcuts;
}
@@ -2202,6 +2213,17 @@
for (ShortcutInfo s : actualShortcuts) {
assertFalse("ID " + s.getId() + " shouldn't have icon res ID", s.hasIconResource());
assertTrue("ID " + s.getId() + " not have icon FD", s.hasIconFile());
+ assertFalse("ID " + s.getId() + " shouldn't have icon URI", s.hasIconUri());
+ }
+ return actualShortcuts;
+ }
+
+ public static List<ShortcutInfo> assertAllHaveIconUri(
+ List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertFalse("ID " + s.getId() + " shouldn't have icon res ID", s.hasIconResource());
+ assertFalse("ID " + s.getId() + " shouldn't have have icon FD", s.hasIconFile());
+ assertTrue("ID " + s.getId() + " not have icon URI", s.hasIconUri());
}
return actualShortcuts;
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 56460fb..2cbb6d5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -114,8 +114,11 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@@ -133,6 +136,16 @@
*/
@SmallTest
public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
+
+ @Override
+ protected void tearDown() throws Exception {
+ deleteUriFile("file32x32.jpg");
+ deleteUriFile("file64x64.jpg");
+ deleteUriFile("file512x512.jpg");
+
+ super.tearDown();
+ }
+
/**
* Test for the first launch path, no settings file available.
*/
@@ -724,6 +737,17 @@
final Icon bmp512x512 = Icon.createWithBitmap(BitmapFactory.decodeResource(
getTestContext().getResources(), R.drawable.black_512x512));
+ // The corresponding files will be deleted in tearDown()
+ final Icon uri32x32 = Icon.createWithContentUri(
+ getFileUriFromResource("file32x32.jpg", R.drawable.black_32x32));
+ final Icon uri64x64_maskable = Icon.createWithAdaptiveBitmapContentUri(
+ getFileUriFromResource("file64x64.jpg", R.drawable.black_64x64));
+ final Icon uri512x512 = Icon.createWithContentUri(
+ getFileUriFromResource("file512x512.jpg", R.drawable.black_512x512));
+
+ doReturn(mUriPermissionOwner.getExternalToken())
+ .when(mMockUriGrantsManagerInternal).newUriPermissionOwner(anyString());
+
// Set from package 1
setCaller(CALLING_PACKAGE_1);
assertTrue(mManager.setDynamicShortcuts(list(
@@ -732,6 +756,9 @@
makeShortcutWithIcon("bmp32x32", bmp32x32),
makeShortcutWithIcon("bmp64x64", bmp64x64_maskable),
makeShortcutWithIcon("bmp512x512", bmp512x512),
+ makeShortcutWithIcon("uri32x32", uri32x32),
+ makeShortcutWithIcon("uri64x64", uri64x64_maskable),
+ makeShortcutWithIcon("uri512x512", uri512x512),
makeShortcut("none")
)));
@@ -742,6 +769,9 @@
"bmp32x32",
"bmp64x64",
"bmp512x512",
+ "uri32x32",
+ "uri64x64",
+ "uri512x512",
"none");
// Call from another caller with the same ID, just to make sure storage is per-package.
@@ -749,11 +779,15 @@
assertTrue(mManager.setDynamicShortcuts(list(
makeShortcutWithIcon("res32x32", res512x512),
makeShortcutWithIcon("res64x64", res512x512),
+ makeShortcutWithIcon("uri32x32", uri512x512),
+ makeShortcutWithIcon("uri64x64", uri512x512),
makeShortcutWithIcon("none", res512x512)
)));
assertShortcutIds(assertAllNotHaveIcon(mManager.getDynamicShortcuts()),
"res32x32",
"res64x64",
+ "uri32x32",
+ "uri64x64",
"none");
// Different profile. Note the names and the contents don't match.
@@ -795,6 +829,18 @@
list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "bmp512x512", USER_0))),
"bmp512x512");
+ assertShortcutIds(assertAllHaveIconUri(
+ list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "uri32x32", USER_0))),
+ "uri32x32");
+
+ assertShortcutIds(assertAllHaveIconUri(
+ list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "uri64x64", USER_0))),
+ "uri64x64");
+
+ assertShortcutIds(assertAllHaveIconUri(
+ list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "uri512x512", USER_0))),
+ "uri512x512");
+
assertShortcutIds(assertAllHaveIconResId(
list(getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "res32x32", USER_P0))),
"res32x32");
@@ -860,15 +906,37 @@
bmp = pfdToBitmap(
mLauncherApps.getShortcutIconFd(CALLING_PACKAGE_1, "bmp32x32", HANDLE_USER_P0));
assertBitmapSize(128, 128, bmp);
+/*
+ bmp = pfdToBitmap(mLauncherApps.getUriShortcutIconFd(
+ getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "uri32x32", USER_0)));
+ assertBitmapSize(32, 32, bmp);
- Drawable dr = mLauncherApps.getShortcutIconDrawable(
+ bmp = pfdToBitmap(mLauncherApps.getUriShortcutIconFd(
+ getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "uri64x64", USER_0)));
+ assertBitmapSize(64, 64, bmp);
+
+ bmp = pfdToBitmap(mLauncherApps.getUriShortcutIconFd(
+ getShortcutInfoAsLauncher(CALLING_PACKAGE_1, "uri512x512", USER_0)));
+ assertBitmapSize(512, 512, bmp);
+*/
+
+ Drawable dr_bmp = mLauncherApps.getShortcutIconDrawable(
makeShortcutWithIcon("bmp64x64", bmp64x64_maskable), 0);
- assertTrue(dr instanceof AdaptiveIconDrawable);
+ assertTrue(dr_bmp instanceof AdaptiveIconDrawable);
float viewportPercentage = 1 / (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
assertEquals((int) (bmp64x64_maskable.getBitmap().getWidth() * viewportPercentage),
- dr.getIntrinsicWidth());
+ dr_bmp.getIntrinsicWidth());
assertEquals((int) (bmp64x64_maskable.getBitmap().getHeight() * viewportPercentage),
- dr.getIntrinsicHeight());
+ dr_bmp.getIntrinsicHeight());
+/*
+ Drawable dr_uri = mLauncherApps.getShortcutIconDrawable(
+ makeShortcutWithIcon("uri64x64", uri64x64_maskable), 0);
+ assertTrue(dr_uri instanceof AdaptiveIconDrawable);
+ assertEquals((int) (bmp64x64_maskable.getBitmap().getWidth() * viewportPercentage),
+ dr_uri.getIntrinsicWidth());
+ assertEquals((int) (bmp64x64_maskable.getBitmap().getHeight() * viewportPercentage),
+ dr_uri.getIntrinsicHeight());
+*/
}
public void testCleanupDanglingBitmaps() throws Exception {
@@ -1274,6 +1342,18 @@
makeShortcut("s1")
)));
+ // Set uri icon
+ assertTrue(mManager.updateShortcuts(list(
+ new ShortcutInfo.Builder(mClientContext, "s1")
+ .setIcon(Icon.createWithContentUri("test_uri"))
+ .build()
+ )));
+ mService.waitForBitmapSavesForTest();
+ assertWith(getCallerShortcuts())
+ .forShortcutWithId("s1", si -> {
+ assertTrue(si.hasIconUri());
+ assertEquals("test_uri", si.getIconUri());
+ });
// Set resource icon
assertTrue(mManager.updateShortcuts(list(
new ShortcutInfo.Builder(mClientContext, "s1")
@@ -1287,6 +1367,9 @@
assertEquals(R.drawable.black_32x32, si.getIconResourceId());
});
mService.waitForBitmapSavesForTest();
+
+ mInjectedCurrentTimeMillis += INTERVAL; // reset throttling
+
// Set bitmap icon
assertTrue(mManager.updateShortcuts(list(
new ShortcutInfo.Builder(mClientContext, "s1")
@@ -1300,9 +1383,7 @@
assertTrue(si.hasIconFile());
});
- mInjectedCurrentTimeMillis += INTERVAL; // reset throttling
-
- // Do it again, with the reverse order (bitmap -> icon)
+ // Do it again, with the reverse order (bitmap -> resource -> uri)
assertTrue(mManager.setDynamicShortcuts(list(
makeShortcut("s1")
)));
@@ -1320,6 +1401,8 @@
assertTrue(si.hasIconFile());
});
+ mInjectedCurrentTimeMillis += INTERVAL; // reset throttling
+
// Set resource icon
assertTrue(mManager.updateShortcuts(list(
new ShortcutInfo.Builder(mClientContext, "s1")
@@ -1332,6 +1415,18 @@
assertTrue(si.hasIconResource());
assertEquals(R.drawable.black_32x32, si.getIconResourceId());
});
+ // Set uri icon
+ assertTrue(mManager.updateShortcuts(list(
+ new ShortcutInfo.Builder(mClientContext, "s1")
+ .setIcon(Icon.createWithContentUri("test_uri"))
+ .build()
+ )));
+ mService.waitForBitmapSavesForTest();
+ assertWith(getCallerShortcuts())
+ .forShortcutWithId("s1", si -> {
+ assertTrue(si.hasIconUri());
+ assertEquals("test_uri", si.getIconUri());
+ });
});
}
@@ -8499,4 +8594,26 @@
}
}
}
+
+ private Uri getFileUriFromResource(String fileName, int resId) throws IOException {
+ File file = new File(getTestContext().getFilesDir(), fileName);
+ // Make sure we are not leaving phantom files behind.
+ assertFalse(file.exists());
+ try (InputStream source = getTestContext().getResources().openRawResource(resId);
+ OutputStream target = new FileOutputStream(file)) {
+ byte[] buffer = new byte[1024];
+ for (int len = source.read(buffer); len >= 0; len = source.read(buffer)) {
+ target.write(buffer, 0, len);
+ }
+ }
+ assertTrue(file.exists());
+ return Uri.fromFile(file);
+ }
+
+ private void deleteUriFile(String fileName) {
+ File file = new File(getTestContext().getFilesDir(), fileName);
+ if (file.exists()) {
+ file.delete();
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 7b101c7..ca77049 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -257,6 +257,7 @@
si.addFlags(ShortcutInfo.FLAG_PINNED);
si.setBitmapPath("abc");
si.setIconResourceId(456);
+ si.setIconUri("test_uri");
si = parceled(si);
@@ -279,6 +280,7 @@
assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals("abc", si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
+ assertEquals("test_uri", si.getIconUri());
assertEquals(0, si.getTitleResId());
assertEquals(null, si.getTitleResName());
@@ -310,6 +312,7 @@
si.addFlags(ShortcutInfo.FLAG_PINNED);
si.setBitmapPath("abc");
si.setIconResourceId(456);
+ si.setIconUri("test_uri");
lookupAndFillInResourceNames(si);
@@ -335,6 +338,7 @@
assertEquals("abc", si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
assertEquals("string/r456", si.getIconResName());
+ assertEquals("test_uri", si.getIconUri());
}
public void testShortcutInfoClone() {
@@ -359,6 +363,7 @@
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
sorig.setIconResourceId(456);
+ sorig.setIconUri("test_uri");
lookupAndFillInResourceNames(sorig);
@@ -386,6 +391,7 @@
assertEquals("abc", si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
assertEquals("string/r456", si.getIconResName());
+ assertEquals("test_uri", si.getIconUri());
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
@@ -407,6 +413,7 @@
assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals(null, si.getBitmapPath());
+ assertNull(si.getIconUri());
assertEquals(456, si.getIconResourceId());
assertEquals(null, si.getIconResName());
@@ -428,6 +435,7 @@
assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals(null, si.getBitmapPath());
+ assertNull(si.getIconUri());
assertEquals(456, si.getIconResourceId());
assertEquals(null, si.getIconResName());
@@ -450,6 +458,7 @@
assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY
| ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals(null, si.getBitmapPath());
+ assertNull(si.getIconUri());
assertEquals(456, si.getIconResourceId());
assertEquals(null, si.getIconResName());
@@ -474,6 +483,7 @@
assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals(null, si.getBitmapPath());
+ assertNull(si.getIconUri());
assertEquals(456, si.getIconResourceId());
assertEquals(null, si.getIconResName());
@@ -499,6 +509,7 @@
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
sorig.setIconResourceId(456);
+ sorig.setIconUri("test_uri");
lookupAndFillInResourceNames(sorig);
@@ -526,6 +537,7 @@
assertEquals("abc", si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
assertEquals("string/r456", si.getIconResName());
+ assertEquals("test_uri", si.getIconUri());
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
@@ -547,6 +559,7 @@
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertEquals(null, si.getBitmapPath());
+ assertNull(si.getIconUri());
assertEquals(456, si.getIconResourceId());
assertEquals(null, si.getIconResName());
@@ -570,6 +583,7 @@
assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
assertEquals(null, si.getBitmapPath());
+ assertNull(si.getIconUri());
assertEquals(456, si.getIconResourceId());
assertEquals(null, si.getIconResName());
@@ -593,6 +607,7 @@
assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY, si.getFlags());
assertEquals(null, si.getBitmapPath());
+ assertNull(si.getIconUri());
assertEquals(456, si.getIconResourceId());
assertEquals(null, si.getIconResName());
@@ -657,6 +672,7 @@
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
sorig.setIconResourceId(456);
+ sorig.setIconUri("test_uri");
lookupAndFillInResourceNames(sorig);
@@ -677,6 +693,7 @@
assertEquals(0, si.getIconResourceId());
assertEquals(null, si.getIconResName());
assertEquals(null, si.getBitmapPath());
+ assertNull(si.getIconUri());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
@@ -787,6 +804,7 @@
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
sorig.setIconResourceId(456);
+ sorig.setIconUri("test_uri");
ShortcutInfo si;
@@ -804,6 +822,7 @@
assertEquals(0, si.getIconResourceId());
assertEquals(null, si.getIconResName());
assertEquals(null, si.getBitmapPath());
+ assertNull(si.getIconUri());
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
@@ -977,6 +996,7 @@
| ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags());
assertNotNull(si.getBitmapPath()); // Something should be set.
assertEquals(0, si.getIconResourceId());
+ assertNull(si.getIconUri());
assertTrue(si.getLastChangedTimestamp() < now);
// Make sure ranks are saved too. Because of the auto-adjusting, we need two shortcuts
@@ -1053,6 +1073,7 @@
si.getFlags());
assertNotNull(si.getBitmapPath()); // Something should be set.
assertEquals(0, si.getIconResourceId());
+ assertNull(si.getIconUri());
assertTrue(si.getLastChangedTimestamp() < now);
dumpUserFile(USER_10);
@@ -1125,6 +1146,7 @@
assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_RES
| ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags());
assertNull(si.getBitmapPath());
+ assertNull(si.getIconUri());
assertEquals(R.drawable.black_32x32, si.getIconResourceId());
assertTrue(si.getLastChangedTimestamp() < now);
@@ -1134,6 +1156,94 @@
assertEquals(1, si.getRank());
}
+ public void testShortcutInfoSaveAndLoad_uri() throws InterruptedException {
+ mRunningUsers.put(USER_10, true);
+
+ setCaller(CALLING_PACKAGE_1, USER_10);
+
+ final Icon uriIcon = Icon.createWithContentUri("test_uri");
+
+ PersistableBundle pb = new PersistableBundle();
+ pb.putInt("k", 1);
+ ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
+ .setId("id")
+ .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
+ .setIcon(uriIcon)
+ .setTitleResId(10)
+ .setTextResId(11)
+ .setDisabledMessageResId(12)
+ .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
+ .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+ .setRank(123)
+ .setExtras(pb)
+ .build();
+ sorig.setTimestamp(mInjectedCurrentTimeMillis);
+
+ final Icon uriMaskableIcon = Icon.createWithAdaptiveBitmapContentUri("uri_maskable");
+
+ ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext)
+ .setId("id2")
+ .setTitle("x")
+ .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
+ .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+ .setRank(456)
+ .setIcon(uriMaskableIcon)
+ .build();
+ sorig2.setTimestamp(mInjectedCurrentTimeMillis);
+
+ mManager.addDynamicShortcuts(list(sorig, sorig2));
+
+ mInjectedCurrentTimeMillis += 1;
+ final long now = mInjectedCurrentTimeMillis;
+ mInjectedCurrentTimeMillis += 1;
+
+ // Save and load.
+ mService.saveDirtyInfo();
+ initService();
+ mService.handleUnlockUser(USER_10);
+
+ ShortcutInfo si;
+ si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
+
+ assertEquals(USER_10, si.getUserId());
+ assertEquals(HANDLE_USER_10, si.getUserHandle());
+ assertEquals(CALLING_PACKAGE_1, si.getPackage());
+ assertEquals("id", si.getId());
+ assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
+ assertEquals(null, si.getIcon());
+ assertEquals(10, si.getTitleResId());
+ assertEquals("r10", si.getTitleResName());
+ assertEquals(11, si.getTextResId());
+ assertEquals("r11", si.getTextResName());
+ assertEquals(12, si.getDisabledMessageResourceId());
+ assertEquals("r12", si.getDisabledMessageResName());
+ assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
+ assertEquals("action", si.getIntent().getAction());
+ assertEquals("val", si.getIntent().getStringExtra("key"));
+ assertEquals(0, si.getRank());
+ assertEquals(1, si.getExtras().getInt("k"));
+
+ assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_URI
+ | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags());
+ assertNull(si.getBitmapPath());
+ assertNull(si.getIconResName());
+ assertEquals(0, si.getIconResourceId());
+ assertEquals("test_uri", si.getIconUri());
+ assertTrue(si.getLastChangedTimestamp() < now);
+
+ // Make sure ranks are saved too. Because of the auto-adjusting, we need two shortcuts
+ // to test it.
+ si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10);
+ assertEquals(1, si.getRank());
+ assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_URI
+ | ShortcutInfo.FLAG_STRINGS_RESOLVED | ShortcutInfo.FLAG_ADAPTIVE_BITMAP,
+ si.getFlags());
+ assertNull(si.getBitmapPath());
+ assertNull(si.getIconResName());
+ assertEquals(0, si.getIconResourceId());
+ assertEquals("uri_maskable", si.getIconUri());
+ }
+
public void testShortcutInfoSaveAndLoad_forBackup() {
setCaller(CALLING_PACKAGE_1, USER_0);
@@ -1196,6 +1306,7 @@
| ShortcutInfo.FLAG_SHADOW , si.getFlags());
assertNull(si.getBitmapPath()); // No icon.
assertEquals(0, si.getIconResourceId());
+ assertNull(si.getIconUri());
// Note when restored from backup, it's no longer dynamic, so shouldn't have a rank.
si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_0);
@@ -1265,6 +1376,77 @@
assertNull(si.getBitmapPath()); // No icon.
assertEquals(0, si.getIconResourceId());
assertEquals(null, si.getIconResName());
+ assertNull(si.getIconUri());
+
+ // Note when restored from backup, it's no longer dynamic, so shouldn't have a rank.
+ si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_0);
+ assertEquals(0, si.getRank());
+ }
+
+ public void testShortcutInfoSaveAndLoad_forBackup_uri() {
+ setCaller(CALLING_PACKAGE_1, USER_0);
+
+ final Icon uriIcon = Icon.createWithContentUri("test_uri");
+
+ PersistableBundle pb = new PersistableBundle();
+ pb.putInt("k", 1);
+ ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
+ .setId("id")
+ .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
+ .setIcon(uriIcon)
+ .setTitleResId(10)
+ .setTextResId(11)
+ .setDisabledMessageResId(12)
+ .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
+ .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+ .setRank(123)
+ .setExtras(pb)
+ .build();
+
+ ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext)
+ .setId("id2")
+ .setTitle("x")
+ .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
+ .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
+ .setRank(456)
+ .build();
+
+ mManager.addDynamicShortcuts(list(sorig, sorig2));
+
+ // Dynamic shortcuts won't be backed up, so we need to pin it.
+ setCaller(LAUNCHER_1, USER_0);
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id", "id2"), HANDLE_USER_0);
+
+ // Do backup & restore.
+ backupAndRestore();
+
+ mService.handleUnlockUser(USER_0); // Load user-0.
+
+ ShortcutInfo si;
+ si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0);
+
+ assertEquals(CALLING_PACKAGE_1, si.getPackage());
+ assertEquals("id", si.getId());
+ assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
+ assertEquals(null, si.getIcon());
+ assertEquals(10, si.getTitleResId());
+ assertEquals("r10", si.getTitleResName());
+ assertEquals(11, si.getTextResId());
+ assertEquals("r11", si.getTextResName());
+ assertEquals(12, si.getDisabledMessageResourceId());
+ assertEquals("r12", si.getDisabledMessageResName());
+ assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
+ assertEquals("action", si.getIntent().getAction());
+ assertEquals("val", si.getIntent().getStringExtra("key"));
+ assertEquals(0, si.getRank());
+ assertEquals(1, si.getExtras().getInt("k"));
+
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_STRINGS_RESOLVED
+ | ShortcutInfo.FLAG_SHADOW , si.getFlags());
+ assertNull(si.getBitmapPath()); // No icon.
+ assertEquals(0, si.getIconResourceId());
+ assertEquals(null, si.getIconResName());
+ assertNull(si.getIconUri());
// Note when restored from backup, it's no longer dynamic, so shouldn't have a rank.
si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_0);
diff --git a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
index 2e60866..bbfc5ab 100644
--- a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
@@ -1275,25 +1275,8 @@
true /* valid */, true /* installed */));
runWebViewBootPreparationOnMainSync();
-
checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation phase */);
- mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
- WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0 /* userId */);
- mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
- WebViewUpdateService.PACKAGE_ADDED_REPLACED, 1 /* userId */);
- mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
- WebViewUpdateService.PACKAGE_ADDED_REPLACED, 2 /* userId */);
- // package still has the same update-time so we shouldn't run preparation here
- Mockito.verify(mTestSystemImpl, Mockito.times(1)).onWebViewProviderChanged(
- Mockito.argThat(new IsPackageInfoWithName(primaryPackage)));
-
- // Ensure we can still load the package
- WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
- assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
- assertEquals(primaryPackage, response.packageInfo.packageName);
-
-
mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
true /* valid */, true /* installed */, null /* signatures */,
20 /* lastUpdateTime*/ ));
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
index 8e78047..010f8ac 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -390,7 +390,7 @@
"title", 0, "titleResName", "text", 0, "textResName",
"disabledMessage", 0, "disabledMessageResName",
null, null, 0, null, 0, 0,
- 0, "iconResName", "bitmapPath", 0,
+ 0, "iconResName", "bitmapPath", null, 0,
null, null);
return si;
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ScheduleConditionProviderTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleConditionProviderTest.java
index 5a527a2..551e186 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ScheduleConditionProviderTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleConditionProviderTest.java
@@ -3,10 +3,8 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
-import android.app.Application;
import android.content.Intent;
import android.net.Uri;
import android.service.notification.Condition;
@@ -47,7 +45,7 @@
null, // ActivityThread not actually used in Service
ScheduleConditionProvider.class.getName(),
null, // token not needed when not talking with the activity manager
- mock(Application.class),
+ null,
null // mocked services don't talk with the activity manager
);
service.onCreate();
diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp
index cdba9a1..6cb8b86 100644
--- a/services/tests/wmtests/Android.bp
+++ b/services/tests/wmtests/Android.bp
@@ -20,6 +20,7 @@
"mockito-target-extended-minus-junit4",
"platform-test-annotations",
"servicestests-utils",
+ "testng",
"truth-prebuilt",
"testables",
"ub-uiautomator",
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
index c449049..2acb647 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
@@ -51,6 +51,7 @@
opts.setLaunchTaskId(Integer.MAX_VALUE);
opts.setLockTaskEnabled(true);
opts.setRotationAnimationHint(ROTATION_ANIMATION_ROTATE);
+ opts.setTaskAlwaysOnTop(true);
opts.setTaskOverlay(true, true);
opts.setSplitScreenCreateMode(SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT);
Bundle optsBundle = opts.toBundle();
@@ -67,6 +68,7 @@
assertEquals(Integer.MAX_VALUE, restoredOpts.getLaunchTaskId());
assertTrue(restoredOpts.getLockTaskMode());
assertEquals(ROTATION_ANIMATION_ROTATE, restoredOpts.getRotationAnimationHint());
+ assertTrue(restoredOpts.getTaskAlwaysOnTop());
assertTrue(restoredOpts.getTaskOverlay());
assertTrue(restoredOpts.canTaskOverlayResume());
assertEquals(SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index af04f76..fc256b0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -246,7 +246,7 @@
}
@Test
- public void testWorkChallenge() {
+ public void testLockedManagedProfile() {
// GIVEN that the user the activity is starting as is currently locked
when(mAmInternal.shouldConfirmCredentials(TEST_USER_ID)).thenReturn(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index e2c27ea..7928e76 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -20,6 +20,9 @@
import static android.view.Gravity.LEFT;
import static android.view.Gravity.RIGHT;
import static android.view.Gravity.TOP;
+import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsState.ITYPE_TOP_GESTURES;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
@@ -42,13 +45,17 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeTrue;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
+import static org.testng.Assert.expectThrows;
import android.app.WindowConfiguration;
import android.graphics.Insets;
@@ -154,6 +161,56 @@
}
@Test
+ public void addingWindow_withInsetsTypes() {
+ WindowState win = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel");
+ win.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR, ITYPE_TOP_GESTURES};
+ win.getFrameLw().set(0, 0, 500, 100);
+
+ addWindow(win);
+ InsetsStateController controller = mDisplayContent.getInsetsStateController();
+ controller.onPostLayout();
+
+ InsetsSourceProvider statusBarProvider = controller.getSourceProvider(ITYPE_STATUS_BAR);
+ assertEquals(new Rect(0, 0, 500, 100), statusBarProvider.getSource().getFrame());
+ assertEquals(Insets.of(0, 100, 0, 0),
+ statusBarProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */));
+
+ InsetsSourceProvider topGesturesProvider = controller.getSourceProvider(ITYPE_TOP_GESTURES);
+ assertEquals(new Rect(0, 0, 500, 100), topGesturesProvider.getSource().getFrame());
+ assertEquals(Insets.of(0, 100, 0, 0),
+ topGesturesProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */));
+
+ InsetsSourceProvider navigationBarProvider = controller.getSourceProvider(
+ ITYPE_NAVIGATION_BAR);
+ assertNotEquals(new Rect(0, 0, 500, 100), navigationBarProvider.getSource().getFrame());
+ }
+
+ @Test
+ public void addingWindow_ignoresInsetsTypes_InWindowTypeWithPredefinedInsets() {
+ mDisplayPolicy.removeWindowLw(mStatusBarWindow); // Removes the existing one.
+ WindowState win = createWindow(null, TYPE_STATUS_BAR, "StatusBar");
+ win.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR};
+ win.getFrameLw().set(0, 0, 500, 100);
+
+ addWindow(win);
+ mDisplayContent.getInsetsStateController().onPostLayout();
+
+ InsetsSourceProvider provider =
+ mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR);
+ assertNotEquals(new Rect(0, 0, 500, 100), provider.getSource().getFrame());
+ }
+
+ @Test
+ public void addingWindow_throwsException_WithMultipleInsetTypes() {
+ WindowState win = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel");
+ win.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
+
+ expectThrows(IllegalArgumentException.class, () -> addWindow(win));
+ }
+
+ @Test
public void layoutWindowLw_fitStatusBars() {
assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index a380ece..bfb126f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
@@ -131,6 +132,21 @@
}
@Test
+ public void testStripForDispatch_multiwindow_alwaysOnTop() {
+ final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
+ final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+
+ getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
+ getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
+ app.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+ app.setAlwaysOnTop(true);
+
+ assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_STATUS_BAR));
+ assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_NAVIGATION_BAR));
+ }
+
+ @Test
public void testImeForDispatch() {
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime");
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index bc81d5e..71c837e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -278,7 +278,7 @@
}
@Test
- public void testContainerChanges() {
+ public void testContainerFocusableChanges() {
removeGlobalMinSizeRestriction();
final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
.setWindowingMode(WINDOWING_MODE_FREEFORM).build();
@@ -288,6 +288,24 @@
t.setFocusable(stack.mRemoteToken, false);
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
assertFalse(task.isFocusable());
+ t.setFocusable(stack.mRemoteToken, true);
+ mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
+ assertTrue(task.isFocusable());
+ }
+
+ @Test
+ public void testContainerHiddenChanges() {
+ removeGlobalMinSizeRestriction();
+ final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
+ WindowContainerTransaction t = new WindowContainerTransaction();
+ assertTrue(stack.shouldBeVisible(null));
+ t.setHidden(stack.mRemoteToken, true);
+ mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
+ assertFalse(stack.shouldBeVisible(null));
+ t.setHidden(stack.mRemoteToken, false);
+ mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
+ assertTrue(stack.shouldBeVisible(null));
}
@Test
@@ -532,6 +550,9 @@
final Task task = createTaskInStack(stackController1, 0 /* userId */);
final ITaskOrganizer organizer = registerMockOrganizer();
+ spyOn(task);
+ doReturn(true).when(task).isVisible();
+
BLASTSyncEngine bse = new BLASTSyncEngine();
BLASTSyncEngine.TransactionReadyListener transactionListener =
@@ -546,6 +567,35 @@
}
@Test
+ public void testOverlappingBLASTCallback() throws RemoteException {
+ final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
+ final Task task = createTaskInStack(stackController1, 0 /* userId */);
+ final ITaskOrganizer organizer = registerMockOrganizer();
+
+ spyOn(task);
+ doReturn(true).when(task).isVisible();
+ final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
+ makeWindowVisible(w);
+
+ BLASTSyncEngine bse = new BLASTSyncEngine();
+
+ BLASTSyncEngine.TransactionReadyListener transactionListener =
+ mock(BLASTSyncEngine.TransactionReadyListener.class);
+
+ int id = bse.startSyncSet(transactionListener);
+ assertEquals(true, bse.addToSyncSet(id, task));
+ bse.setReady(id);
+
+ int id2 = bse.startSyncSet(transactionListener);
+ // We should be rejected from the second sync since we are already
+ // in one.
+ assertEquals(false, bse.addToSyncSet(id2, task));
+ w.finishDrawing(null);
+ assertEquals(true, bse.addToSyncSet(id2, task));
+ bse.setReady(id2);
+ }
+
+ @Test
public void testBLASTCallbackWithWindow() {
final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stackController1, 0 /* userId */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
index 2fb0b4c..8f913dd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
@@ -81,9 +81,9 @@
assertEquals(TEST_INSETS, snapshot.getContentInsets());
assertNotNull(snapshot.getSnapshot());
assertEquals(Configuration.ORIENTATION_PORTRAIT, snapshot.getOrientation());
+ assertNull(mLoader.loadTask(1, mTestUserId, true /* isLowResolution */));
}
-
@Test
public void testRemoveObsoleteFiles() {
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
@@ -132,10 +132,18 @@
assertNull(mCache.getSnapshot(window.getTask().mTaskId, mWm.mCurrentUserId,
false /* restoreFromDisk */, false /* isLowResolution */));
- // Load it from disk
+ // Attempt to load the low-res snapshot from the disk
assertNull(mCache.getSnapshot(window.getTask().mTaskId, mWm.mCurrentUserId,
true /* restoreFromDisk */, true /* isLowResolution */));
+ // Load the high-res (default) snapshot from disk
+ assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, mWm.mCurrentUserId,
+ true /* restoreFromDisk */, false /* isLowResolution */));
+
+ // Make sure it's not in the cache now.
+ assertNull(mCache.getSnapshot(window.getTask().mTaskId, mWm.mCurrentUserId,
+ false /* restoreFromDisk */, true /* isLowResolution */));
+
// Make sure it's not in the cache now.
assertNull(mCache.getSnapshot(window.getTask().mTaskId, mWm.mCurrentUserId,
false /* restoreFromDisk */, false /* isLowResolution */));
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index 9a9abba..bfee894 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -293,35 +293,6 @@
}
@Test
- public void testDisabledLowResolutionPersistAndLoadSnapshot() {
- mPersister.setEnableLowResSnapshots(false);
-
- TaskSnapshot a = new TaskSnapshotBuilder()
- .setScaleFraction(0.5f)
- .setIsLowResolution(true)
- .build();
- assertTrue(a.isLowResolution());
- mPersister.persistSnapshot(1, mTestUserId, a);
- mPersister.waitForQueueEmpty();
- final File[] files = new File[]{new File(FILES_DIR.getPath() + "/snapshots/1.proto"),
- new File(FILES_DIR.getPath() + "/snapshots/1.jpg")};
- final File[] nonExistsFiles = new File[]{
- new File(FILES_DIR.getPath() + "/snapshots/1_reduced.jpg"),
- };
- assertTrueForFiles(files, File::exists, " must exist");
- assertTrueForFiles(nonExistsFiles, file -> !file.exists(), " must not exist");
- final TaskSnapshot snapshot = mLoader.loadTask(1, mTestUserId, false /* isLowResolution */);
- assertNotNull(snapshot);
- assertEquals(TEST_INSETS, snapshot.getContentInsets());
- assertNotNull(snapshot.getSnapshot());
- assertEquals(Configuration.ORIENTATION_PORTRAIT, snapshot.getOrientation());
-
- final TaskSnapshot snapshotNotExist = mLoader.loadTask(1, mTestUserId,
- true /* isLowResolution */);
- assertNull(snapshotNotExist);
- }
-
- @Test
public void testIsRealSnapshotPersistAndLoadSnapshot() {
TaskSnapshot a = new TaskSnapshotBuilder()
.setIsRealSnapshot(true)
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index 6d78658..88de34d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -127,7 +127,6 @@
private static final int SNAPSHOT_HEIGHT = 100;
private float mScaleFraction = 1f;
- private boolean mIsLowResolution = false;
private boolean mIsRealSnapshot = true;
private boolean mIsTranslucent = false;
private int mWindowingMode = WINDOWING_MODE_FULLSCREEN;
@@ -142,11 +141,6 @@
return this;
}
- TaskSnapshotBuilder setIsLowResolution(boolean isLowResolution) {
- mIsLowResolution = isLowResolution;
- return this;
- }
-
TaskSnapshotBuilder setIsRealSnapshot(boolean isRealSnapshot) {
mIsRealSnapshot = isRealSnapshot;
return this;
@@ -186,8 +180,11 @@
return new TaskSnapshot(MOCK_SNAPSHOT_ID, new ComponentName("", ""), buffer,
ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
mRotation, taskSize, TEST_INSETS,
- mIsLowResolution, mIsRealSnapshot,
- mWindowingMode, mSystemUiVisibility, mIsTranslucent);
+ // When building a TaskSnapshot with the Builder class, isLowResolution
+ // is always false. Low-res snapshots are only created when loading from
+ // disk.
+ false /* isLowResolution */,
+ mIsRealSnapshot, mWindowingMode, mSystemUiVisibility, mIsTranslucent);
}
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java
index ce6efdf..926bd8c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java
@@ -24,6 +24,9 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import android.content.ContentResolver;
import android.net.Uri;
@@ -60,11 +63,35 @@
public void testFreeformWindow() {
try (SettingsSession freeformWindowSession = new
SettingsSession(DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT)) {
- final boolean freeformWindow = !freeformWindowSession.getSetting();
- final Uri freeformWindowUri = freeformWindowSession.setSetting(freeformWindow);
+ final boolean curFreeformWindow = freeformWindowSession.getSetting();
+ final boolean newFreeformWindow = !curFreeformWindow;
+ final Uri freeformWindowUri = freeformWindowSession.setSetting(newFreeformWindow);
+ mWm.mAtmService.mSupportsFreeformWindowManagement = curFreeformWindow;
mWm.mSettingsObserver.onChange(false, freeformWindowUri);
- assertEquals(mWm.mAtmService.mSupportsFreeformWindowManagement, freeformWindow);
+ assertEquals(mWm.mAtmService.mSupportsFreeformWindowManagement, newFreeformWindow);
+ }
+ }
+
+ @Test
+ public void testFreeformWindow_valueChanged_updatesDisplaySettings() {
+ try (SettingsSession freeformWindowSession = new
+ SettingsSession(DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT)) {
+ final boolean curFreeformWindow = freeformWindowSession.getSetting();
+ final boolean newFreeformWindow = !curFreeformWindow;
+ final Uri freeformWindowUri = freeformWindowSession.setSetting(newFreeformWindow);
+ mWm.mAtmService.mSupportsFreeformWindowManagement = curFreeformWindow;
+ clearInvocations(mWm.mRoot);
+ mWm.mSettingsObserver.onChange(false, freeformWindowUri);
+
+ // Changed value should update display settings.
+ verify(mWm.mRoot).onSettingsRetrieved();
+
+ clearInvocations(mWm.mRoot);
+ mWm.mSettingsObserver.onChange(false, freeformWindowUri);
+
+ // Unchanged value should not update display settings.
+ verify(mWm.mRoot, never()).onSettingsRetrieved();
}
}
@@ -73,7 +100,8 @@
try (SettingsSession forceResizableSession = new
SettingsSession(DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES)) {
final boolean forceResizableMode = !forceResizableSession.getSetting();
- final Uri forceResizableUri = forceResizableSession.setSetting(forceResizableMode);
+ final Uri forceResizableUri = forceResizableSession.setSetting(forceResizableMode);
+
mWm.mSettingsObserver.onChange(false, forceResizableUri);
assertEquals(mWm.mAtmService.mForceResizableActivities, forceResizableMode);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 8e85bb2..747c8d9 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -445,7 +445,6 @@
abstract static class UsbHandler extends Handler {
// current USB state
- private boolean mConnected;
private boolean mHostConnected;
private boolean mSourcePower;
private boolean mSinkPower;
@@ -473,6 +472,7 @@
private final UsbPermissionManager mPermissionManager;
private NotificationManager mNotificationManager;
+ protected boolean mConnected;
protected long mScreenUnlockedFunctions;
protected boolean mBootCompleted;
protected boolean mCurrentFunctionsApplied;
@@ -1794,7 +1794,8 @@
case MSG_SET_FUNCTIONS_TIMEOUT:
Slog.e(TAG, "Set functions timed out! no reply from usb hal");
if (msg.arg1 != 1) {
- setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
+ // Set this since default function may be selected from Developer options
+ setEnabledFunctions(mScreenUnlockedFunctions, false);
}
break;
case MSG_GET_CURRENT_USB_FUNCTIONS:
@@ -1816,7 +1817,8 @@
* Dont force to default when the configuration is already set to default.
*/
if (msg.arg1 != 1) {
- setEnabledFunctions(UsbManager.FUNCTION_NONE, !isAdbEnabled());
+ // Set this since default function may be selected from Developer options
+ setEnabledFunctions(mScreenUnlockedFunctions, false);
}
break;
case MSG_GADGET_HAL_REGISTERED:
@@ -1936,8 +1938,11 @@
SET_FUNCTIONS_TIMEOUT_MS - SET_FUNCTIONS_LEEWAY_MS);
sendMessageDelayed(MSG_SET_FUNCTIONS_TIMEOUT, chargingFunctions,
SET_FUNCTIONS_TIMEOUT_MS);
- sendMessageDelayed(MSG_FUNCTION_SWITCH_TIMEOUT, chargingFunctions,
- SET_FUNCTIONS_TIMEOUT_MS + ENUMERATION_TIME_OUT_MS);
+ if (mConnected) {
+ // Only queue timeout of enumeration when the USB is connected
+ sendMessageDelayed(MSG_FUNCTION_SWITCH_TIMEOUT, chargingFunctions,
+ SET_FUNCTIONS_TIMEOUT_MS + ENUMERATION_TIME_OUT_MS);
+ }
if (DEBUG) Slog.d(TAG, "timeout message queued");
} catch (RemoteException e) {
Slog.e(TAG, "Remoteexception while calling setCurrentUsbFunctions", e);
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 767010a..3196758 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -19,6 +19,7 @@
import static android.Manifest.permission.BIND_SOUND_TRIGGER_DETECTION_SERVICE;
import static android.content.Context.BIND_AUTO_CREATE;
import static android.content.Context.BIND_FOREGROUND_SERVICE;
+import static android.content.Context.BIND_INCLUDE_CAPABILITIES;
import static android.content.pm.PackageManager.GET_META_DATA;
import static android.content.pm.PackageManager.GET_SERVICES;
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
@@ -1133,7 +1134,8 @@
}
mIsBound = mContext.bindServiceAsUser(i, this,
- BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE, mUser);
+ BIND_AUTO_CREATE | BIND_FOREGROUND_SERVICE | BIND_INCLUDE_CAPABILITIES,
+ mUser);
if (mIsBound) {
mRemoteServiceWakeLock.acquire();
diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt
new file mode 100644
index 0000000..11568f1
--- /dev/null
+++ b/telephony/api/system-current.txt
@@ -0,0 +1,2142 @@
+// Signature format: 2.0
+package android.telephony {
+
+ public final class AccessNetworkConstants {
+ field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff
+ }
+
+ public static final class AccessNetworkConstants.NgranBands {
+ method public static int getFrequencyRangeGroup(int);
+ field public static final int FREQUENCY_RANGE_GROUP_1 = 1; // 0x1
+ field public static final int FREQUENCY_RANGE_GROUP_2 = 2; // 0x2
+ field public static final int FREQUENCY_RANGE_GROUP_UNKNOWN = 0; // 0x0
+ }
+
+ public final class BarringInfo implements android.os.Parcelable {
+ ctor public BarringInfo();
+ method @NonNull public android.telephony.BarringInfo createLocationInfoSanitizedCopy();
+ }
+
+ public final class CallAttributes implements android.os.Parcelable {
+ ctor public CallAttributes(@NonNull android.telephony.PreciseCallState, int, @NonNull android.telephony.CallQuality);
+ method public int describeContents();
+ method @NonNull public android.telephony.CallQuality getCallQuality();
+ method public int getNetworkType();
+ method @NonNull public android.telephony.PreciseCallState getPreciseCallState();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR;
+ }
+
+ public final class CallQuality implements android.os.Parcelable {
+ ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int);
+ ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int, boolean, boolean, boolean);
+ method public int describeContents();
+ method public int getAverageRelativeJitter();
+ method public int getAverageRoundTripTime();
+ method public int getCallDuration();
+ method public int getCodecType();
+ method public int getDownlinkCallQualityLevel();
+ method public int getMaxRelativeJitter();
+ method public int getNumRtpPacketsNotReceived();
+ method public int getNumRtpPacketsReceived();
+ method public int getNumRtpPacketsTransmitted();
+ method public int getNumRtpPacketsTransmittedLost();
+ method public int getUplinkCallQualityLevel();
+ method public boolean isIncomingSilenceDetected();
+ method public boolean isOutgoingSilenceDetected();
+ method public boolean isRtpInactivityDetected();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CALL_QUALITY_BAD = 4; // 0x4
+ field public static final int CALL_QUALITY_EXCELLENT = 0; // 0x0
+ field public static final int CALL_QUALITY_FAIR = 2; // 0x2
+ field public static final int CALL_QUALITY_GOOD = 1; // 0x1
+ field public static final int CALL_QUALITY_NOT_AVAILABLE = 5; // 0x5
+ field public static final int CALL_QUALITY_POOR = 3; // 0x3
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallQuality> CREATOR;
+ }
+
+ public class CarrierConfigManager {
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultCarrierServicePackageName();
+ method @NonNull public static android.os.PersistableBundle getDefaultConfig();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void updateConfigForPhoneId(int, String);
+ field public static final String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
+ field public static final String KEY_SUPPORT_CDMA_1X_VOICE_CALLS_BOOL = "support_cdma_1x_voice_calls_bool";
+ }
+
+ public static final class CarrierConfigManager.Wifi {
+ field public static final String KEY_HOTSPOT_MAX_CLIENT_COUNT = "wifi.hotspot_maximum_client_count";
+ field public static final String KEY_PREFIX = "wifi.";
+ }
+
+ public final class CarrierRestrictionRules implements android.os.Parcelable {
+ method @NonNull public java.util.List<java.lang.Boolean> areCarrierIdentifiersAllowed(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>);
+ method public int describeContents();
+ method @NonNull public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers();
+ method public int getDefaultCarrierRestriction();
+ method @NonNull public java.util.List<android.service.carrier.CarrierIdentifier> getExcludedCarriers();
+ method public int getMultiSimPolicy();
+ method public boolean isAllCarriersAllowed();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CARRIER_RESTRICTION_DEFAULT_ALLOWED = 1; // 0x1
+ field public static final int CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CarrierRestrictionRules> CREATOR;
+ field public static final int MULTISIM_POLICY_NONE = 0; // 0x0
+ field public static final int MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT = 1; // 0x1
+ }
+
+ public static final class CarrierRestrictionRules.Builder {
+ ctor public CarrierRestrictionRules.Builder();
+ method @NonNull public android.telephony.CarrierRestrictionRules build();
+ method @NonNull public android.telephony.CarrierRestrictionRules.Builder setAllCarriersAllowed();
+ method @NonNull public android.telephony.CarrierRestrictionRules.Builder setAllowedCarriers(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>);
+ method @NonNull public android.telephony.CarrierRestrictionRules.Builder setDefaultCarrierRestriction(int);
+ method @NonNull public android.telephony.CarrierRestrictionRules.Builder setExcludedCarriers(@NonNull java.util.List<android.service.carrier.CarrierIdentifier>);
+ method @NonNull public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int);
+ }
+
+ public class CbGeoUtils {
+ }
+
+ public static class CbGeoUtils.Circle implements android.telephony.CbGeoUtils.Geometry {
+ ctor public CbGeoUtils.Circle(@NonNull android.telephony.CbGeoUtils.LatLng, double);
+ method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
+ method @NonNull public android.telephony.CbGeoUtils.LatLng getCenter();
+ method public double getRadius();
+ }
+
+ public static interface CbGeoUtils.Geometry {
+ method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
+ }
+
+ public static class CbGeoUtils.LatLng {
+ ctor public CbGeoUtils.LatLng(double, double);
+ method public double distance(@NonNull android.telephony.CbGeoUtils.LatLng);
+ method @NonNull public android.telephony.CbGeoUtils.LatLng subtract(@NonNull android.telephony.CbGeoUtils.LatLng);
+ field public final double lat;
+ field public final double lng;
+ }
+
+ public static class CbGeoUtils.Polygon implements android.telephony.CbGeoUtils.Geometry {
+ ctor public CbGeoUtils.Polygon(@NonNull java.util.List<android.telephony.CbGeoUtils.LatLng>);
+ method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
+ method @NonNull public java.util.List<android.telephony.CbGeoUtils.LatLng> getVertices();
+ }
+
+ public abstract class CellBroadcastService extends android.app.Service {
+ ctor public CellBroadcastService();
+ method @NonNull @WorkerThread public abstract CharSequence getCellBroadcastAreaInfo(int);
+ method public android.os.IBinder onBind(@Nullable android.content.Intent);
+ method public abstract void onCdmaCellBroadcastSms(int, @NonNull byte[], int);
+ method public abstract void onCdmaScpMessage(int, @NonNull java.util.List<android.telephony.cdma.CdmaSmsCbProgramData>, @NonNull String, @NonNull java.util.function.Consumer<android.os.Bundle>);
+ method public abstract void onGsmCellBroadcastSms(int, @NonNull byte[]);
+ field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService";
+ }
+
+ public abstract class CellIdentity implements android.os.Parcelable {
+ method @NonNull public abstract android.telephony.CellLocation asCellLocation();
+ method @NonNull public abstract android.telephony.CellIdentity sanitizeLocationInfo();
+ }
+
+ public final class CellIdentityCdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.cdma.CdmaCellLocation asCellLocation();
+ method @NonNull public android.telephony.CellIdentityCdma sanitizeLocationInfo();
+ }
+
+ public final class CellIdentityGsm extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ method @NonNull public android.telephony.CellIdentityGsm sanitizeLocationInfo();
+ }
+
+ public final class CellIdentityLte extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ method @NonNull public android.telephony.CellIdentityLte sanitizeLocationInfo();
+ }
+
+ public final class CellIdentityNr extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.CellLocation asCellLocation();
+ method @NonNull public android.telephony.CellIdentityNr sanitizeLocationInfo();
+ }
+
+ public final class CellIdentityTdscdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ method @NonNull public android.telephony.CellIdentityTdscdma sanitizeLocationInfo();
+ }
+
+ public final class CellIdentityWcdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ method @NonNull public android.telephony.CellIdentityWcdma sanitizeLocationInfo();
+ }
+
+ public final class DataFailCause {
+ field @Deprecated public static final int VSNCP_APN_UNATHORIZED = 2238; // 0x8be
+ }
+
+ public final class DataSpecificRegistrationInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.telephony.LteVopsSupportInfo getLteVopsSupportInfo();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR;
+ }
+
+ public final class DisconnectCause {
+ field public static final int ALREADY_DIALING = 72; // 0x48
+ field public static final int ANSWERED_ELSEWHERE = 52; // 0x34
+ field public static final int BUSY = 4; // 0x4
+ field public static final int CALLING_DISABLED = 74; // 0x4a
+ field public static final int CALL_BARRED = 20; // 0x14
+ field public static final int CALL_PULLED = 51; // 0x33
+ field public static final int CANT_CALL_WHILE_RINGING = 73; // 0x49
+ field public static final int CDMA_ACCESS_BLOCKED = 35; // 0x23
+ field public static final int CDMA_ACCESS_FAILURE = 32; // 0x20
+ field public static final int CDMA_ALREADY_ACTIVATED = 49; // 0x31
+ field public static final int CDMA_DROP = 27; // 0x1b
+ field public static final int CDMA_INTERCEPT = 28; // 0x1c
+ field public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE = 26; // 0x1a
+ field public static final int CDMA_NOT_EMERGENCY = 34; // 0x22
+ field public static final int CDMA_PREEMPTED = 33; // 0x21
+ field public static final int CDMA_REORDER = 29; // 0x1d
+ field public static final int CDMA_RETRY_ORDER = 31; // 0x1f
+ field public static final int CDMA_SO_REJECT = 30; // 0x1e
+ field public static final int CONGESTION = 5; // 0x5
+ field public static final int CS_RESTRICTED = 22; // 0x16
+ field public static final int CS_RESTRICTED_EMERGENCY = 24; // 0x18
+ field public static final int CS_RESTRICTED_NORMAL = 23; // 0x17
+ field public static final int DATA_DISABLED = 54; // 0x36
+ field public static final int DATA_LIMIT_REACHED = 55; // 0x37
+ field public static final int DIALED_CALL_FORWARDING_WHILE_ROAMING = 57; // 0x39
+ field public static final int DIALED_MMI = 39; // 0x27
+ field public static final int DIAL_LOW_BATTERY = 62; // 0x3e
+ field public static final int DIAL_MODIFIED_TO_DIAL = 48; // 0x30
+ field public static final int DIAL_MODIFIED_TO_DIAL_VIDEO = 66; // 0x42
+ field public static final int DIAL_MODIFIED_TO_SS = 47; // 0x2f
+ field public static final int DIAL_MODIFIED_TO_USSD = 46; // 0x2e
+ field public static final int DIAL_VIDEO_MODIFIED_TO_DIAL = 69; // 0x45
+ field public static final int DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO = 70; // 0x46
+ field public static final int DIAL_VIDEO_MODIFIED_TO_SS = 67; // 0x43
+ field public static final int DIAL_VIDEO_MODIFIED_TO_USSD = 68; // 0x44
+ field public static final int EMERGENCY_PERM_FAILURE = 64; // 0x40
+ field public static final int EMERGENCY_TEMP_FAILURE = 63; // 0x3f
+ field public static final int ERROR_UNSPECIFIED = 36; // 0x24
+ field public static final int FDN_BLOCKED = 21; // 0x15
+ field public static final int ICC_ERROR = 19; // 0x13
+ field public static final int IMEI_NOT_ACCEPTED = 58; // 0x3a
+ field public static final int IMS_ACCESS_BLOCKED = 60; // 0x3c
+ field public static final int IMS_MERGED_SUCCESSFULLY = 45; // 0x2d
+ field public static final int IMS_SIP_ALTERNATE_EMERGENCY_CALL = 71; // 0x47
+ field public static final int INCOMING_AUTO_REJECTED = 81; // 0x51
+ field public static final int INCOMING_MISSED = 1; // 0x1
+ field public static final int INCOMING_REJECTED = 16; // 0x10
+ field public static final int INVALID_CREDENTIALS = 10; // 0xa
+ field public static final int INVALID_NUMBER = 7; // 0x7
+ field public static final int LIMIT_EXCEEDED = 15; // 0xf
+ field public static final int LOCAL = 3; // 0x3
+ field public static final int LOST_SIGNAL = 14; // 0xe
+ field public static final int LOW_BATTERY = 61; // 0x3d
+ field public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED = 53; // 0x35
+ field public static final int MMI = 6; // 0x6
+ field public static final int NORMAL = 2; // 0x2
+ field public static final int NORMAL_UNSPECIFIED = 65; // 0x41
+ field public static final int NOT_DISCONNECTED = 0; // 0x0
+ field public static final int NOT_VALID = -1; // 0xffffffff
+ field public static final int NO_PHONE_NUMBER_SUPPLIED = 38; // 0x26
+ field public static final int NUMBER_UNREACHABLE = 8; // 0x8
+ field public static final int OTASP_PROVISIONING_IN_PROCESS = 76; // 0x4c
+ field public static final int OUTGOING_CANCELED = 44; // 0x2c
+ field public static final int OUTGOING_EMERGENCY_CALL_PLACED = 80; // 0x50
+ field public static final int OUTGOING_FAILURE = 43; // 0x2b
+ field public static final int OUT_OF_NETWORK = 11; // 0xb
+ field public static final int OUT_OF_SERVICE = 18; // 0x12
+ field public static final int POWER_OFF = 17; // 0x11
+ field public static final int SERVER_ERROR = 12; // 0xc
+ field public static final int SERVER_UNREACHABLE = 9; // 0x9
+ field public static final int TIMED_OUT = 13; // 0xd
+ field public static final int TOO_MANY_ONGOING_CALLS = 75; // 0x4b
+ field public static final int UNOBTAINABLE_NUMBER = 25; // 0x19
+ field public static final int VIDEO_CALL_NOT_ALLOWED_WHILE_TTY_ENABLED = 50; // 0x32
+ field public static final int VOICEMAIL_NUMBER_MISSING = 40; // 0x28
+ field public static final int WIFI_LOST = 59; // 0x3b
+ }
+
+ public final class ImsiEncryptionInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public String getKeyIdentifier();
+ method @Nullable public java.security.PublicKey getPublicKey();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ImsiEncryptionInfo> CREATOR;
+ }
+
+ public final class LteVopsSupportInfo implements android.os.Parcelable {
+ ctor public LteVopsSupportInfo(int, int);
+ method public int describeContents();
+ method public int getEmcBearerSupport();
+ method public int getVopsSupport();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.LteVopsSupportInfo> CREATOR;
+ field public static final int LTE_STATUS_NOT_AVAILABLE = 1; // 0x1
+ field public static final int LTE_STATUS_NOT_SUPPORTED = 3; // 0x3
+ field public static final int LTE_STATUS_SUPPORTED = 2; // 0x2
+ }
+
+ public class MbmsDownloadSession implements java.lang.AutoCloseable {
+ field public static final String MBMS_DOWNLOAD_SERVICE_ACTION = "android.telephony.action.EmbmsDownload";
+ }
+
+ public class MbmsGroupCallSession implements java.lang.AutoCloseable {
+ field public static final String MBMS_GROUP_CALL_SERVICE_ACTION = "android.telephony.action.EmbmsGroupCall";
+ }
+
+ public class MbmsStreamingSession implements java.lang.AutoCloseable {
+ field public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming";
+ }
+
+ public final class ModemActivityInfo implements android.os.Parcelable {
+ ctor public ModemActivityInfo(long, int, int, @NonNull int[], int);
+ method public int describeContents();
+ method public int getIdleTimeMillis();
+ method public int getReceiveTimeMillis();
+ method public int getSleepTimeMillis();
+ method public long getTimestamp();
+ method @NonNull public java.util.List<android.telephony.ModemActivityInfo.TransmitPower> getTransmitPowerInfo();
+ method public boolean isValid();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR;
+ field public static final int TX_POWER_LEVELS = 5; // 0x5
+ field public static final int TX_POWER_LEVEL_0 = 0; // 0x0
+ field public static final int TX_POWER_LEVEL_1 = 1; // 0x1
+ field public static final int TX_POWER_LEVEL_2 = 2; // 0x2
+ field public static final int TX_POWER_LEVEL_3 = 3; // 0x3
+ field public static final int TX_POWER_LEVEL_4 = 4; // 0x4
+ }
+
+ public class ModemActivityInfo.TransmitPower {
+ method @NonNull public android.util.Range<java.lang.Integer> getPowerRangeInDbm();
+ method public int getTimeInMillis();
+ }
+
+ public final class NetworkRegistrationInfo implements android.os.Parcelable {
+ method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo();
+ method public int getRegistrationState();
+ method public int getRejectCause();
+ method public int getRoamingType();
+ method public boolean isEmergencyEnabled();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int REGISTRATION_STATE_DENIED = 3; // 0x3
+ field public static final int REGISTRATION_STATE_HOME = 1; // 0x1
+ field public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0; // 0x0
+ field public static final int REGISTRATION_STATE_NOT_REGISTERED_SEARCHING = 2; // 0x2
+ field public static final int REGISTRATION_STATE_ROAMING = 5; // 0x5
+ field public static final int REGISTRATION_STATE_UNKNOWN = 4; // 0x4
+ }
+
+ public static final class NetworkRegistrationInfo.Builder {
+ ctor public NetworkRegistrationInfo.Builder();
+ method @NonNull public android.telephony.NetworkRegistrationInfo build();
+ method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAccessNetworkTechnology(int);
+ method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setAvailableServices(@NonNull java.util.List<java.lang.Integer>);
+ method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setCellIdentity(@Nullable android.telephony.CellIdentity);
+ method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setDomain(int);
+ method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setEmergencyOnly(boolean);
+ method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegisteredPlmn(@Nullable String);
+ method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRegistrationState(int);
+ method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setRejectCause(int);
+ method @NonNull public android.telephony.NetworkRegistrationInfo.Builder setTransportType(int);
+ }
+
+ public abstract class NetworkService extends android.app.Service {
+ ctor public NetworkService();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method @Nullable public abstract android.telephony.NetworkService.NetworkServiceProvider onCreateNetworkServiceProvider(int);
+ field public static final String SERVICE_INTERFACE = "android.telephony.NetworkService";
+ }
+
+ public abstract class NetworkService.NetworkServiceProvider implements java.lang.AutoCloseable {
+ ctor public NetworkService.NetworkServiceProvider(int);
+ method public abstract void close();
+ method public final int getSlotIndex();
+ method public final void notifyNetworkRegistrationInfoChanged();
+ method public void requestNetworkRegistrationInfo(int, @NonNull android.telephony.NetworkServiceCallback);
+ }
+
+ public class NetworkServiceCallback {
+ method public void onRequestNetworkRegistrationInfoComplete(int, @Nullable android.telephony.NetworkRegistrationInfo);
+ field public static final int RESULT_ERROR_BUSY = 3; // 0x3
+ field public static final int RESULT_ERROR_FAILED = 5; // 0x5
+ field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4
+ field public static final int RESULT_ERROR_INVALID_ARG = 2; // 0x2
+ field public static final int RESULT_ERROR_UNSUPPORTED = 1; // 0x1
+ field public static final int RESULT_SUCCESS = 0; // 0x0
+ }
+
+ public interface NumberVerificationCallback {
+ method public default void onCallReceived(@NonNull String);
+ method public default void onVerificationFailed(int);
+ field public static final int REASON_CONCURRENT_REQUESTS = 4; // 0x4
+ field public static final int REASON_IN_ECBM = 5; // 0x5
+ field public static final int REASON_IN_EMERGENCY_CALL = 6; // 0x6
+ field public static final int REASON_NETWORK_NOT_AVAILABLE = 2; // 0x2
+ field public static final int REASON_TIMED_OUT = 1; // 0x1
+ field public static final int REASON_TOO_MANY_CALLS = 3; // 0x3
+ field public static final int REASON_UNSPECIFIED = 0; // 0x0
+ }
+
+ public final class PhoneNumberRange implements android.os.Parcelable {
+ ctor public PhoneNumberRange(@NonNull String, @NonNull String, @NonNull String, @NonNull String);
+ method public int describeContents();
+ method public boolean matches(@NonNull String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneNumberRange> CREATOR;
+ }
+
+ public class PhoneNumberUtils {
+ method @NonNull public static String getUsernameFromUriNumber(@NonNull String);
+ method public static boolean isUriNumber(@Nullable String);
+ method public static boolean isVoiceMailNumber(@NonNull android.content.Context, int, @Nullable String);
+ }
+
+ public final class PreciseCallState implements android.os.Parcelable {
+ ctor public PreciseCallState(int, int, int, int, int);
+ method public int describeContents();
+ method public int getBackgroundCallState();
+ method public int getForegroundCallState();
+ method public int getRingingCallState();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PreciseCallState> CREATOR;
+ field public static final int PRECISE_CALL_STATE_ACTIVE = 1; // 0x1
+ field public static final int PRECISE_CALL_STATE_ALERTING = 4; // 0x4
+ field public static final int PRECISE_CALL_STATE_DIALING = 3; // 0x3
+ field public static final int PRECISE_CALL_STATE_DISCONNECTED = 7; // 0x7
+ field public static final int PRECISE_CALL_STATE_DISCONNECTING = 8; // 0x8
+ field public static final int PRECISE_CALL_STATE_HOLDING = 2; // 0x2
+ field public static final int PRECISE_CALL_STATE_IDLE = 0; // 0x0
+ field public static final int PRECISE_CALL_STATE_INCOMING = 5; // 0x5
+ field public static final int PRECISE_CALL_STATE_NOT_VALID = -1; // 0xffffffff
+ field public static final int PRECISE_CALL_STATE_WAITING = 6; // 0x6
+ }
+
+ public final class PreciseDataConnectionState implements android.os.Parcelable {
+ method @Deprecated @NonNull public String getDataConnectionApn();
+ method @Deprecated public int getDataConnectionApnTypeBitMask();
+ method @Deprecated public int getDataConnectionFailCause();
+ method @Deprecated @Nullable public android.net.LinkProperties getDataConnectionLinkProperties();
+ method @Deprecated public int getDataConnectionNetworkType();
+ method @Deprecated public int getDataConnectionState();
+ }
+
+ public final class PreciseDisconnectCause {
+ field public static final int ACCESS_CLASS_BLOCKED = 260; // 0x104
+ field public static final int ACCESS_INFORMATION_DISCARDED = 43; // 0x2b
+ field public static final int ACM_LIMIT_EXCEEDED = 68; // 0x44
+ field public static final int BEARER_CAPABILITY_NOT_AUTHORIZED = 57; // 0x39
+ field public static final int BEARER_NOT_AVAIL = 58; // 0x3a
+ field public static final int BEARER_SERVICE_NOT_IMPLEMENTED = 65; // 0x41
+ field public static final int BUSY = 17; // 0x11
+ field public static final int CALL_BARRED = 240; // 0xf0
+ field public static final int CALL_REJECTED = 21; // 0x15
+ field public static final int CDMA_ACCESS_BLOCKED = 1009; // 0x3f1
+ field public static final int CDMA_ACCESS_FAILURE = 1006; // 0x3ee
+ field public static final int CDMA_DROP = 1001; // 0x3e9
+ field public static final int CDMA_INTERCEPT = 1002; // 0x3ea
+ field public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE = 1000; // 0x3e8
+ field public static final int CDMA_NOT_EMERGENCY = 1008; // 0x3f0
+ field public static final int CDMA_PREEMPTED = 1007; // 0x3ef
+ field public static final int CDMA_REORDER = 1003; // 0x3eb
+ field public static final int CDMA_RETRY_ORDER = 1005; // 0x3ed
+ field public static final int CDMA_SO_REJECT = 1004; // 0x3ec
+ field public static final int CHANNEL_NOT_AVAIL = 44; // 0x2c
+ field public static final int CHANNEL_UNACCEPTABLE = 6; // 0x6
+ field public static final int CONDITIONAL_IE_ERROR = 100; // 0x64
+ field public static final int DESTINATION_OUT_OF_ORDER = 27; // 0x1b
+ field public static final int ERROR_UNSPECIFIED = 65535; // 0xffff
+ field public static final int FACILITY_REJECTED = 29; // 0x1d
+ field public static final int FDN_BLOCKED = 241; // 0xf1
+ field public static final int IMEI_NOT_ACCEPTED = 243; // 0xf3
+ field public static final int IMSI_UNKNOWN_IN_VLR = 242; // 0xf2
+ field public static final int INCOMING_CALLS_BARRED_WITHIN_CUG = 55; // 0x37
+ field public static final int INCOMPATIBLE_DESTINATION = 88; // 0x58
+ field public static final int INFORMATION_ELEMENT_NON_EXISTENT = 99; // 0x63
+ field public static final int INTERWORKING_UNSPECIFIED = 127; // 0x7f
+ field public static final int INVALID_MANDATORY_INFORMATION = 96; // 0x60
+ field public static final int INVALID_NUMBER_FORMAT = 28; // 0x1c
+ field public static final int INVALID_TRANSACTION_IDENTIFIER = 81; // 0x51
+ field public static final int MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101; // 0x65
+ field public static final int MESSAGE_TYPE_NON_IMPLEMENTED = 97; // 0x61
+ field public static final int MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98; // 0x62
+ field public static final int NETWORK_DETACH = 261; // 0x105
+ field public static final int NETWORK_OUT_OF_ORDER = 38; // 0x26
+ field public static final int NETWORK_REJECT = 252; // 0xfc
+ field public static final int NETWORK_RESP_TIMEOUT = 251; // 0xfb
+ field public static final int NORMAL = 16; // 0x10
+ field public static final int NORMAL_UNSPECIFIED = 31; // 0x1f
+ field public static final int NOT_VALID = -1; // 0xffffffff
+ field public static final int NO_ANSWER_FROM_USER = 19; // 0x13
+ field public static final int NO_CIRCUIT_AVAIL = 34; // 0x22
+ field public static final int NO_DISCONNECT_CAUSE_AVAILABLE = 0; // 0x0
+ field public static final int NO_ROUTE_TO_DESTINATION = 3; // 0x3
+ field public static final int NO_USER_RESPONDING = 18; // 0x12
+ field public static final int NO_VALID_SIM = 249; // 0xf9
+ field public static final int NUMBER_CHANGED = 22; // 0x16
+ field public static final int OEM_CAUSE_1 = 61441; // 0xf001
+ field public static final int OEM_CAUSE_10 = 61450; // 0xf00a
+ field public static final int OEM_CAUSE_11 = 61451; // 0xf00b
+ field public static final int OEM_CAUSE_12 = 61452; // 0xf00c
+ field public static final int OEM_CAUSE_13 = 61453; // 0xf00d
+ field public static final int OEM_CAUSE_14 = 61454; // 0xf00e
+ field public static final int OEM_CAUSE_15 = 61455; // 0xf00f
+ field public static final int OEM_CAUSE_2 = 61442; // 0xf002
+ field public static final int OEM_CAUSE_3 = 61443; // 0xf003
+ field public static final int OEM_CAUSE_4 = 61444; // 0xf004
+ field public static final int OEM_CAUSE_5 = 61445; // 0xf005
+ field public static final int OEM_CAUSE_6 = 61446; // 0xf006
+ field public static final int OEM_CAUSE_7 = 61447; // 0xf007
+ field public static final int OEM_CAUSE_8 = 61448; // 0xf008
+ field public static final int OEM_CAUSE_9 = 61449; // 0xf009
+ field public static final int ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE = 70; // 0x46
+ field public static final int OPERATOR_DETERMINED_BARRING = 8; // 0x8
+ field public static final int OUT_OF_SRV = 248; // 0xf8
+ field public static final int PREEMPTION = 25; // 0x19
+ field public static final int PROTOCOL_ERROR_UNSPECIFIED = 111; // 0x6f
+ field public static final int QOS_NOT_AVAIL = 49; // 0x31
+ field public static final int RADIO_ACCESS_FAILURE = 253; // 0xfd
+ field public static final int RADIO_INTERNAL_ERROR = 250; // 0xfa
+ field public static final int RADIO_LINK_FAILURE = 254; // 0xfe
+ field public static final int RADIO_LINK_LOST = 255; // 0xff
+ field public static final int RADIO_OFF = 247; // 0xf7
+ field public static final int RADIO_RELEASE_ABNORMAL = 259; // 0x103
+ field public static final int RADIO_RELEASE_NORMAL = 258; // 0x102
+ field public static final int RADIO_SETUP_FAILURE = 257; // 0x101
+ field public static final int RADIO_UPLINK_FAILURE = 256; // 0x100
+ field public static final int RECOVERY_ON_TIMER_EXPIRED = 102; // 0x66
+ field public static final int REQUESTED_FACILITY_NOT_IMPLEMENTED = 69; // 0x45
+ field public static final int REQUESTED_FACILITY_NOT_SUBSCRIBED = 50; // 0x32
+ field public static final int RESOURCES_UNAVAILABLE_OR_UNSPECIFIED = 47; // 0x2f
+ field public static final int SEMANTICALLY_INCORRECT_MESSAGE = 95; // 0x5f
+ field public static final int SERVICE_OPTION_NOT_AVAILABLE = 63; // 0x3f
+ field public static final int SERVICE_OR_OPTION_NOT_IMPLEMENTED = 79; // 0x4f
+ field public static final int STATUS_ENQUIRY = 30; // 0x1e
+ field public static final int SWITCHING_CONGESTION = 42; // 0x2a
+ field public static final int TEMPORARY_FAILURE = 41; // 0x29
+ field public static final int UNOBTAINABLE_NUMBER = 1; // 0x1
+ field public static final int USER_NOT_MEMBER_OF_CUG = 87; // 0x57
+ }
+
+ public class ServiceState implements android.os.Parcelable {
+ method public void fillInNotifierBundle(@NonNull android.os.Bundle);
+ method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int);
+ method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForDomain(int);
+ method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForTransportType(int);
+ method @NonNull public static android.telephony.ServiceState newFromBundle(@NonNull android.os.Bundle);
+ field public static final int ROAMING_TYPE_DOMESTIC = 2; // 0x2
+ field public static final int ROAMING_TYPE_INTERNATIONAL = 3; // 0x3
+ field public static final int ROAMING_TYPE_NOT_ROAMING = 0; // 0x0
+ field public static final int ROAMING_TYPE_UNKNOWN = 1; // 0x1
+ }
+
+ public class SignalStrength implements android.os.Parcelable {
+ ctor public SignalStrength(@NonNull android.telephony.SignalStrength);
+ }
+
+ public final class SmsCbCmasInfo implements android.os.Parcelable {
+ ctor public SmsCbCmasInfo(int, int, int, int, int, int);
+ method public int describeContents();
+ method public int getCategory();
+ method public int getCertainty();
+ method public int getMessageClass();
+ method public int getResponseType();
+ method public int getSeverity();
+ method public int getUrgency();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CMAS_CATEGORY_CBRNE = 10; // 0xa
+ field public static final int CMAS_CATEGORY_ENV = 7; // 0x7
+ field public static final int CMAS_CATEGORY_FIRE = 5; // 0x5
+ field public static final int CMAS_CATEGORY_GEO = 0; // 0x0
+ field public static final int CMAS_CATEGORY_HEALTH = 6; // 0x6
+ field public static final int CMAS_CATEGORY_INFRA = 9; // 0x9
+ field public static final int CMAS_CATEGORY_MET = 1; // 0x1
+ field public static final int CMAS_CATEGORY_OTHER = 11; // 0xb
+ field public static final int CMAS_CATEGORY_RESCUE = 4; // 0x4
+ field public static final int CMAS_CATEGORY_SAFETY = 2; // 0x2
+ field public static final int CMAS_CATEGORY_SECURITY = 3; // 0x3
+ field public static final int CMAS_CATEGORY_TRANSPORT = 8; // 0x8
+ field public static final int CMAS_CATEGORY_UNKNOWN = -1; // 0xffffffff
+ field public static final int CMAS_CERTAINTY_LIKELY = 1; // 0x1
+ field public static final int CMAS_CERTAINTY_OBSERVED = 0; // 0x0
+ field public static final int CMAS_CERTAINTY_UNKNOWN = -1; // 0xffffffff
+ field public static final int CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY = 3; // 0x3
+ field public static final int CMAS_CLASS_CMAS_EXERCISE = 5; // 0x5
+ field public static final int CMAS_CLASS_EXTREME_THREAT = 1; // 0x1
+ field public static final int CMAS_CLASS_OPERATOR_DEFINED_USE = 6; // 0x6
+ field public static final int CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT = 0; // 0x0
+ field public static final int CMAS_CLASS_REQUIRED_MONTHLY_TEST = 4; // 0x4
+ field public static final int CMAS_CLASS_SEVERE_THREAT = 2; // 0x2
+ field public static final int CMAS_CLASS_UNKNOWN = -1; // 0xffffffff
+ field public static final int CMAS_RESPONSE_TYPE_ASSESS = 6; // 0x6
+ field public static final int CMAS_RESPONSE_TYPE_AVOID = 5; // 0x5
+ field public static final int CMAS_RESPONSE_TYPE_EVACUATE = 1; // 0x1
+ field public static final int CMAS_RESPONSE_TYPE_EXECUTE = 3; // 0x3
+ field public static final int CMAS_RESPONSE_TYPE_MONITOR = 4; // 0x4
+ field public static final int CMAS_RESPONSE_TYPE_NONE = 7; // 0x7
+ field public static final int CMAS_RESPONSE_TYPE_PREPARE = 2; // 0x2
+ field public static final int CMAS_RESPONSE_TYPE_SHELTER = 0; // 0x0
+ field public static final int CMAS_RESPONSE_TYPE_UNKNOWN = -1; // 0xffffffff
+ field public static final int CMAS_SEVERITY_EXTREME = 0; // 0x0
+ field public static final int CMAS_SEVERITY_SEVERE = 1; // 0x1
+ field public static final int CMAS_SEVERITY_UNKNOWN = -1; // 0xffffffff
+ field public static final int CMAS_URGENCY_EXPECTED = 1; // 0x1
+ field public static final int CMAS_URGENCY_IMMEDIATE = 0; // 0x0
+ field public static final int CMAS_URGENCY_UNKNOWN = -1; // 0xffffffff
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbCmasInfo> CREATOR;
+ }
+
+ public final class SmsCbEtwsInfo implements android.os.Parcelable {
+ ctor public SmsCbEtwsInfo(int, boolean, boolean, boolean, @Nullable byte[]);
+ method public int describeContents();
+ method @Nullable public byte[] getPrimaryNotificationSignature();
+ method public long getPrimaryNotificationTimestamp();
+ method public int getWarningType();
+ method public boolean isEmergencyUserAlert();
+ method public boolean isPopupAlert();
+ method public boolean isPrimary();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbEtwsInfo> CREATOR;
+ field public static final int ETWS_WARNING_TYPE_EARTHQUAKE = 0; // 0x0
+ field public static final int ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI = 2; // 0x2
+ field public static final int ETWS_WARNING_TYPE_OTHER_EMERGENCY = 4; // 0x4
+ field public static final int ETWS_WARNING_TYPE_TEST_MESSAGE = 3; // 0x3
+ field public static final int ETWS_WARNING_TYPE_TSUNAMI = 1; // 0x1
+ field public static final int ETWS_WARNING_TYPE_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public final class SmsCbLocation implements android.os.Parcelable {
+ ctor public SmsCbLocation(@NonNull String, int, int);
+ method public int describeContents();
+ method public int getCid();
+ method public int getLac();
+ method @NonNull public String getPlmn();
+ method public boolean isInLocationArea(@NonNull android.telephony.SmsCbLocation);
+ method public boolean isInLocationArea(@Nullable String, int, int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbLocation> CREATOR;
+ }
+
+ public final class SmsCbMessage implements android.os.Parcelable {
+ ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, int, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int, int);
+ method @NonNull public static android.telephony.SmsCbMessage createFromCursor(@NonNull android.database.Cursor);
+ method public int describeContents();
+ method @Nullable public android.telephony.SmsCbCmasInfo getCmasWarningInfo();
+ method @NonNull public android.content.ContentValues getContentValues();
+ method public int getDataCodingScheme();
+ method @Nullable public android.telephony.SmsCbEtwsInfo getEtwsWarningInfo();
+ method public int getGeographicalScope();
+ method @NonNull public java.util.List<android.telephony.CbGeoUtils.Geometry> getGeometries();
+ method @Nullable public String getLanguageCode();
+ method @NonNull public android.telephony.SmsCbLocation getLocation();
+ method public int getMaximumWaitingDuration();
+ method @Nullable public String getMessageBody();
+ method public int getMessageFormat();
+ method public int getMessagePriority();
+ method public long getReceivedTime();
+ method public int getSerialNumber();
+ method public int getServiceCategory();
+ method public int getSlotIndex();
+ method public int getSubscriptionId();
+ method public boolean isCmasMessage();
+ method public boolean isEmergencyMessage();
+ method public boolean isEtwsMessage();
+ method public boolean needGeoFencingCheck();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SmsCbMessage> CREATOR;
+ field public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE = 3; // 0x3
+ field public static final int GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE = 0; // 0x0
+ field public static final int GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE = 2; // 0x2
+ field public static final int GEOGRAPHICAL_SCOPE_PLMN_WIDE = 1; // 0x1
+ field public static final int MAXIMUM_WAIT_TIME_NOT_SET = 255; // 0xff
+ field public static final int MESSAGE_FORMAT_3GPP = 1; // 0x1
+ field public static final int MESSAGE_FORMAT_3GPP2 = 2; // 0x2
+ field public static final int MESSAGE_PRIORITY_EMERGENCY = 3; // 0x3
+ field public static final int MESSAGE_PRIORITY_INTERACTIVE = 1; // 0x1
+ field public static final int MESSAGE_PRIORITY_NORMAL = 0; // 0x0
+ field public static final int MESSAGE_PRIORITY_URGENT = 2; // 0x2
+ }
+
+ public final class SmsManager {
+ method @RequiresPermission(android.Manifest.permission.ACCESS_MESSAGES_ON_ICC) public boolean copyMessageToIcc(@Nullable byte[], @NonNull byte[], int);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_MESSAGES_ON_ICC) public boolean deleteMessageFromIcc(int);
+ method public boolean disableCellBroadcastRange(int, int, int);
+ method public boolean enableCellBroadcastRange(int, int, int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_MESSAGES_ON_ICC) public java.util.List<android.telephony.SmsMessage> getMessagesFromIcc();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getPremiumSmsConsent(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSmsCapacityOnIcc();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPremiumSmsConsent(@NonNull String, int);
+ field public static final int PREMIUM_SMS_CONSENT_ALWAYS_ALLOW = 3; // 0x3
+ field public static final int PREMIUM_SMS_CONSENT_ASK_USER = 1; // 0x1
+ field public static final int PREMIUM_SMS_CONSENT_NEVER_ALLOW = 2; // 0x2
+ field public static final int PREMIUM_SMS_CONSENT_UNKNOWN = 0; // 0x0
+ }
+
+ public class SmsMessage {
+ method @Nullable public static android.telephony.SmsMessage createFromNativeSmsSubmitPdu(@NonNull byte[], boolean);
+ method @Nullable public static android.telephony.SmsMessage.SubmitPdu getSmsPdu(int, int, @Nullable String, @NonNull String, @NonNull String, long);
+ method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static byte[] getSubmitPduEncodedMessage(boolean, @NonNull String, @NonNull String, int, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0, to=255) int, @IntRange(from=1, to=255) int, @IntRange(from=1, to=255) int);
+ }
+
+ public class SubscriptionInfo implements android.os.Parcelable {
+ method public boolean areUiccApplicationsEnabled();
+ method @Nullable public java.util.List<android.telephony.UiccAccessRule> getAccessRules();
+ method public int getProfileClass();
+ method public boolean isGroupDisabled();
+ }
+
+ public class SubscriptionManager {
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean canDisablePhysicalSubscription();
+ method public boolean canManageSubscription(@NonNull android.telephony.SubscriptionInfo, @NonNull String);
+ method @NonNull public int[] getActiveAndHiddenSubscriptionIdList();
+ method @NonNull public int[] getActiveSubscriptionIdList();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String);
+ method public java.util.List<android.telephony.SubscriptionInfo> getAvailableSubscriptionInfoList();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEnabledSubscriptionId(int);
+ method @NonNull public static android.content.res.Resources getResourcesForSubId(@NonNull android.content.Context, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSubscriptionEnabled(int);
+ method public void requestEmbeddedSubscriptionInfoListRefresh();
+ method public void requestEmbeddedSubscriptionInfoListRefresh(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultDataSubId(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultSmsSubId(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultVoiceSubscriptionId(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setDisplayName(@Nullable String, int, int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setIconTint(int, int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUiccApplicationsEnabled(int, boolean);
+ field @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS) public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED";
+ field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
+ field public static final int PROFILE_CLASS_DEFAULT = -1; // 0xffffffff
+ field public static final int PROFILE_CLASS_OPERATIONAL = 2; // 0x2
+ field public static final int PROFILE_CLASS_PROVISIONING = 1; // 0x1
+ field public static final int PROFILE_CLASS_TESTING = 0; // 0x0
+ field public static final int PROFILE_CLASS_UNSET = -1; // 0xffffffff
+ field @NonNull public static final android.net.Uri VT_ENABLED_CONTENT_URI;
+ field @NonNull public static final android.net.Uri WFC_ENABLED_CONTENT_URI;
+ field @NonNull public static final android.net.Uri WFC_MODE_CONTENT_URI;
+ field @NonNull public static final android.net.Uri WFC_ROAMING_ENABLED_CONTENT_URI;
+ field @NonNull public static final android.net.Uri WFC_ROAMING_MODE_CONTENT_URI;
+ }
+
+ public class TelephonyFrameworkInitializer {
+ method public static void registerServiceWrappers();
+ method public static void setTelephonyServiceManager(@NonNull android.os.TelephonyServiceManager);
+ }
+
+ public final class TelephonyHistogram implements android.os.Parcelable {
+ ctor public TelephonyHistogram(int, int, int);
+ ctor public TelephonyHistogram(android.telephony.TelephonyHistogram);
+ ctor public TelephonyHistogram(android.os.Parcel);
+ method public void addTimeTaken(int);
+ method public int describeContents();
+ method public int getAverageTime();
+ method public int getBucketCount();
+ method public int[] getBucketCounters();
+ method public int[] getBucketEndPoints();
+ method public int getCategory();
+ method public int getId();
+ method public int getMaxTime();
+ method public int getMinTime();
+ method public int getSampleCount();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.TelephonyHistogram> CREATOR;
+ field public static final int TELEPHONY_CATEGORY_RIL = 1; // 0x1
+ }
+
+ public class TelephonyManager {
+ method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
+ method public int checkCarrierPrivilegesForPackage(String);
+ method public int checkCarrierPrivilegesForPackageAnyPhone(String);
+ method public void dial(String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean disableDataConnectivity();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableDataConnectivity();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableModemForSlot(int, boolean);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean);
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes();
+ method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
+ method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
+ method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin(int);
+ method public String getCdmaPrlVersion();
+ method public int getCurrentPhoneType();
+ method public int getCurrentPhoneType(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getDataActivationState();
+ method @Deprecated public boolean getDataEnabled();
+ method @Deprecated public boolean getDataEnabled(int);
+ method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getDefaultRespondViaMessageApplication();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceSoftwareVersion(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getEmergencyCallbackMode();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
+ method public int getMaxNumberOfSimultaneouslyActiveSims();
+ method public static long getMaxNumberVerificationTimeoutMillis();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String[] getMergedImsisFromGroup();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
+ method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
+ method public int getSimApplicationState();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int);
+ method public int getSimCardState();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
+ method @Nullable public android.os.Bundle getVisualVoicemailSettings();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoiceActivationState();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmi(String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handlePinMmiForSubscriber(int, String);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean iccCloseLogicalChannelBySlot(int, int);
+ method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(int, @Nullable String, int);
+ method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, @Nullable String);
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, @Nullable String);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAnyRadioPoweredOn();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApnMetered(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isApplicationOnUicc(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataConnectionAllowed();
+ method public boolean isDataConnectivityPossible();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataEnabledForApn(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isEmergencyAssistanceEnabled();
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isInEmergencySmsMode();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isLteCdmaEvdoGsmWcdmaEnabled();
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isOpportunisticNetworkEnabled();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn();
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isTetheringApnRequired();
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled();
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean matchesCurrentSimOperator(@NonNull String, int, @Nullable String);
+ method public boolean needsOtaServiceProvisioning();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyUserActivity();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean);
+ method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
+ method public void requestModemActivityInfo(@NonNull android.os.ResultReceiver);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetAllCarrierActions();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void resetIms(int);
+ method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void resetOtaEmergencyNumberDbFilePath();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
+ method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
+ method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAlwaysAllowMmsData(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataRoamingEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setMultiSimCarrierRestriction(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunisticNetworkState(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setPreferredNetworkTypeBitmask(long);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadio(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRadioEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setRadioPower(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>);
+ method @Deprecated public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoiceActivationState(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void shutdownAllRadios();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPin(String);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
+ method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
+ method public void updateServiceLocation();
+ field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
+ field public static final String ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE = "com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE";
+ field public static final String ACTION_CARRIER_SIGNAL_PCO_VALUE = "com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE";
+ field public static final String ACTION_CARRIER_SIGNAL_REDIRECTED = "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED";
+ field public static final String ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED = "com.android.internal.telephony.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED";
+ field public static final String ACTION_CARRIER_SIGNAL_RESET = "com.android.internal.telephony.CARRIER_SIGNAL_RESET";
+ field public static final String ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED";
+ field public static final String ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED = "android.intent.action.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED";
+ field public static final String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE";
+ field public static final String ACTION_EMERGENCY_CALLBACK_MODE_CHANGED = "android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED";
+ field public static final String ACTION_EMERGENCY_CALL_STATE_CHANGED = "android.intent.action.EMERGENCY_CALL_STATE_CHANGED";
+ field public static final String ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE = "com.android.omadm.service.CONFIGURATION_UPDATE";
+ field public static final String ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS = "android.telephony.action.SHOW_NOTICE_ECM_BLOCK_OTHERS";
+ field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
+ field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
+ field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
+ field public static final int CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES = -2; // 0xfffffffe
+ field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
+ field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
+ field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
+ field public static final String EXTRA_ANOMALY_DESCRIPTION = "android.telephony.extra.ANOMALY_DESCRIPTION";
+ field public static final String EXTRA_ANOMALY_ID = "android.telephony.extra.ANOMALY_ID";
+ field @Deprecated public static final String EXTRA_APN_PROTOCOL = "apnProto";
+ field public static final String EXTRA_APN_PROTOCOL_INT = "apnProtoInt";
+ field @Deprecated public static final String EXTRA_APN_TYPE = "apnType";
+ field public static final String EXTRA_APN_TYPE_INT = "apnTypeInt";
+ field public static final String EXTRA_DEFAULT_NETWORK_AVAILABLE = "defaultNetworkAvailable";
+ field public static final String EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE = "android.telephony.extra.DEFAULT_SUBSCRIPTION_SELECT_TYPE";
+ field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL = 4; // 0x4
+ field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA = 1; // 0x1
+ field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE = 0; // 0x0
+ field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_SMS = 3; // 0x3
+ field public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_VOICE = 2; // 0x2
+ 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_COMBINATION_NAMES = "android.telephony.extra.SIM_COMBINATION_NAMES";
+ field public static final String EXTRA_SIM_COMBINATION_WARNING_TYPE = "android.telephony.extra.SIM_COMBINATION_WARNING_TYPE";
+ field public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA = 1; // 0x1
+ field public static final int EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE = 0; // 0x0
+ 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";
+ field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
+ field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
+ field public static final int KEY_TYPE_EPDG = 1; // 0x1
+ field public static final int KEY_TYPE_WLAN = 2; // 0x2
+ field public static final String MODEM_ACTIVITY_RESULT_KEY = "controller_activity";
+ field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
+ field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
+ field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
+ field public static final long NETWORK_TYPE_BITMASK_EHRPD = 8192L; // 0x2000L
+ field public static final long NETWORK_TYPE_BITMASK_EVDO_0 = 16L; // 0x10L
+ field public static final long NETWORK_TYPE_BITMASK_EVDO_A = 32L; // 0x20L
+ field public static final long NETWORK_TYPE_BITMASK_EVDO_B = 2048L; // 0x800L
+ field public static final long NETWORK_TYPE_BITMASK_GPRS = 1L; // 0x1L
+ field public static final long NETWORK_TYPE_BITMASK_GSM = 32768L; // 0x8000L
+ field public static final long NETWORK_TYPE_BITMASK_HSDPA = 128L; // 0x80L
+ field public static final long NETWORK_TYPE_BITMASK_HSPA = 512L; // 0x200L
+ field public static final long NETWORK_TYPE_BITMASK_HSPAP = 16384L; // 0x4000L
+ field public static final long NETWORK_TYPE_BITMASK_HSUPA = 256L; // 0x100L
+ field public static final long NETWORK_TYPE_BITMASK_IWLAN = 131072L; // 0x20000L
+ field public static final long NETWORK_TYPE_BITMASK_LTE = 4096L; // 0x1000L
+ field public static final long NETWORK_TYPE_BITMASK_LTE_CA = 262144L; // 0x40000L
+ field public static final long NETWORK_TYPE_BITMASK_NR = 524288L; // 0x80000L
+ field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L
+ field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L
+ field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L
+ field public static final int RADIO_POWER_OFF = 0; // 0x0
+ field public static final int RADIO_POWER_ON = 1; // 0x1
+ field public static final int RADIO_POWER_UNAVAILABLE = 2; // 0x2
+ field public static final int SET_CARRIER_RESTRICTION_ERROR = 2; // 0x2
+ field public static final int SET_CARRIER_RESTRICTION_NOT_SUPPORTED = 1; // 0x1
+ field public static final int SET_CARRIER_RESTRICTION_SUCCESS = 0; // 0x0
+ field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2
+ field public static final int SIM_ACTIVATION_STATE_ACTIVATING = 1; // 0x1
+ field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3
+ field public static final int SIM_ACTIVATION_STATE_RESTRICTED = 4; // 0x4
+ field public static final int SIM_ACTIVATION_STATE_UNKNOWN = 0; // 0x0
+ field public static final int SIM_STATE_LOADED = 10; // 0xa
+ field public static final int SIM_STATE_PRESENT = 11; // 0xb
+ field public static final int SRVCC_STATE_HANDOVER_CANCELED = 3; // 0x3
+ field public static final int SRVCC_STATE_HANDOVER_COMPLETED = 1; // 0x1
+ field public static final int SRVCC_STATE_HANDOVER_FAILED = 2; // 0x2
+ field public static final int SRVCC_STATE_HANDOVER_NONE = -1; // 0xffffffff
+ field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0
+ }
+
+ public final class UiccAccessRule implements android.os.Parcelable {
+ ctor public UiccAccessRule(byte[], @Nullable String, long);
+ method public int describeContents();
+ method public int getCarrierPrivilegeStatus(android.content.pm.PackageInfo);
+ method public int getCarrierPrivilegeStatus(android.content.pm.Signature, String);
+ method public String getCertificateHexString();
+ method @Nullable public String getPackageName();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccAccessRule> CREATOR;
+ }
+
+ public class UiccSlotInfo implements android.os.Parcelable {
+ ctor @Deprecated public UiccSlotInfo(boolean, boolean, String, int, int, boolean);
+ method public int describeContents();
+ method public String getCardId();
+ method public int getCardStateInfo();
+ method public boolean getIsActive();
+ method public boolean getIsEuicc();
+ method public boolean getIsExtendedApduSupported();
+ method public int getLogicalSlotIdx();
+ method public boolean isRemovable();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1
+ field public static final int CARD_STATE_INFO_ERROR = 3; // 0x3
+ field public static final int CARD_STATE_INFO_PRESENT = 2; // 0x2
+ field public static final int CARD_STATE_INFO_RESTRICTED = 4; // 0x4
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccSlotInfo> CREATOR;
+ }
+
+ public abstract class VisualVoicemailService extends android.app.Service {
+ method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, String, short, String, android.app.PendingIntent);
+ method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings);
+ }
+
+}
+
+package android.telephony.cdma {
+
+ public final class CdmaSmsCbProgramData implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getCategory();
+ method public int getOperation();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY = 4099; // 0x1003
+ field public static final int CATEGORY_CMAS_EXTREME_THREAT = 4097; // 0x1001
+ field public static final int CATEGORY_CMAS_LAST_RESERVED_VALUE = 4351; // 0x10ff
+ field public static final int CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT = 4096; // 0x1000
+ field public static final int CATEGORY_CMAS_SEVERE_THREAT = 4098; // 0x1002
+ field public static final int CATEGORY_CMAS_TEST_MESSAGE = 4100; // 0x1004
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.cdma.CdmaSmsCbProgramData> CREATOR;
+ field public static final int OPERATION_ADD_CATEGORY = 1; // 0x1
+ field public static final int OPERATION_CLEAR_CATEGORIES = 2; // 0x2
+ field public static final int OPERATION_DELETE_CATEGORY = 0; // 0x0
+ }
+
+}
+
+package android.telephony.data {
+
+ public final class DataCallResponse implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.net.LinkAddress> getAddresses();
+ method public int getCause();
+ method @NonNull public java.util.List<java.net.InetAddress> getDnsAddresses();
+ method @NonNull public java.util.List<java.net.InetAddress> getGatewayAddresses();
+ method public int getId();
+ method @NonNull public String getInterfaceName();
+ method public int getLinkStatus();
+ method @Deprecated public int getMtu();
+ method public int getMtuV4();
+ method public int getMtuV6();
+ method @NonNull public java.util.List<java.net.InetAddress> getPcscfAddresses();
+ method public int getProtocolType();
+ method public int getSuggestedRetryTime();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataCallResponse> CREATOR;
+ field public static final int LINK_STATUS_ACTIVE = 2; // 0x2
+ field public static final int LINK_STATUS_DORMANT = 1; // 0x1
+ field public static final int LINK_STATUS_INACTIVE = 0; // 0x0
+ field public static final int LINK_STATUS_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public static final class DataCallResponse.Builder {
+ ctor public DataCallResponse.Builder();
+ method @NonNull public android.telephony.data.DataCallResponse build();
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setAddresses(@NonNull java.util.List<android.net.LinkAddress>);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setCause(int);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setDnsAddresses(@NonNull java.util.List<java.net.InetAddress>);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setGatewayAddresses(@NonNull java.util.List<java.net.InetAddress>);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setId(int);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setInterfaceName(@NonNull String);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setLinkStatus(int);
+ method @Deprecated @NonNull public android.telephony.data.DataCallResponse.Builder setMtu(int);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV4(int);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setMtuV6(int);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setPcscfAddresses(@NonNull java.util.List<java.net.InetAddress>);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setProtocolType(int);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setSuggestedRetryTime(int);
+ }
+
+ public final class DataProfile implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public String getApn();
+ method public int getAuthType();
+ method public int getBearerBitmask();
+ method @Deprecated public int getMtu();
+ method public int getMtuV4();
+ method public int getMtuV6();
+ method @Nullable public String getPassword();
+ method public int getProfileId();
+ method public int getProtocolType();
+ method public int getRoamingProtocolType();
+ method public int getSupportedApnTypesBitmask();
+ method public int getType();
+ method @Nullable public String getUserName();
+ method public boolean isEnabled();
+ method public boolean isPersistent();
+ method public boolean isPreferred();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataProfile> CREATOR;
+ field public static final int TYPE_3GPP = 1; // 0x1
+ field public static final int TYPE_3GPP2 = 2; // 0x2
+ field public static final int TYPE_COMMON = 0; // 0x0
+ }
+
+ public static final class DataProfile.Builder {
+ ctor public DataProfile.Builder();
+ method @NonNull public android.telephony.data.DataProfile build();
+ method @NonNull public android.telephony.data.DataProfile.Builder enable(boolean);
+ method @NonNull public android.telephony.data.DataProfile.Builder setApn(@NonNull String);
+ method @NonNull public android.telephony.data.DataProfile.Builder setAuthType(int);
+ method @NonNull public android.telephony.data.DataProfile.Builder setBearerBitmask(int);
+ method @Deprecated @NonNull public android.telephony.data.DataProfile.Builder setMtu(int);
+ method @NonNull public android.telephony.data.DataProfile.Builder setMtuV4(int);
+ method @NonNull public android.telephony.data.DataProfile.Builder setMtuV6(int);
+ method @NonNull public android.telephony.data.DataProfile.Builder setPassword(@NonNull String);
+ method @NonNull public android.telephony.data.DataProfile.Builder setPersistent(boolean);
+ method @NonNull public android.telephony.data.DataProfile.Builder setPreferred(boolean);
+ method @NonNull public android.telephony.data.DataProfile.Builder setProfileId(int);
+ method @NonNull public android.telephony.data.DataProfile.Builder setProtocolType(int);
+ method @NonNull public android.telephony.data.DataProfile.Builder setRoamingProtocolType(int);
+ method @NonNull public android.telephony.data.DataProfile.Builder setSupportedApnTypesBitmask(int);
+ method @NonNull public android.telephony.data.DataProfile.Builder setType(int);
+ method @NonNull public android.telephony.data.DataProfile.Builder setUserName(@NonNull String);
+ }
+
+ public abstract class DataService extends android.app.Service {
+ ctor public DataService();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method @Nullable public abstract android.telephony.data.DataService.DataServiceProvider onCreateDataServiceProvider(int);
+ field public static final int REQUEST_REASON_HANDOVER = 3; // 0x3
+ field public static final int REQUEST_REASON_NORMAL = 1; // 0x1
+ field public static final int REQUEST_REASON_SHUTDOWN = 2; // 0x2
+ field public static final int REQUEST_REASON_UNKNOWN = 0; // 0x0
+ field public static final String SERVICE_INTERFACE = "android.telephony.data.DataService";
+ }
+
+ public abstract class DataService.DataServiceProvider implements java.lang.AutoCloseable {
+ ctor public DataService.DataServiceProvider(int);
+ method public abstract void close();
+ method public void deactivateDataCall(int, int, @Nullable android.telephony.data.DataServiceCallback);
+ method public final int getSlotIndex();
+ method public final void notifyDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>);
+ method public void requestDataCallList(@NonNull android.telephony.data.DataServiceCallback);
+ method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @NonNull android.telephony.data.DataServiceCallback);
+ method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @NonNull android.telephony.data.DataServiceCallback);
+ method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @NonNull android.telephony.data.DataServiceCallback);
+ }
+
+ public class DataServiceCallback {
+ method public void onDataCallListChanged(@NonNull java.util.List<android.telephony.data.DataCallResponse>);
+ method public void onDeactivateDataCallComplete(int);
+ method public void onRequestDataCallListComplete(int, @NonNull java.util.List<android.telephony.data.DataCallResponse>);
+ method public void onSetDataProfileComplete(int);
+ method public void onSetInitialAttachApnComplete(int);
+ method public void onSetupDataCallComplete(int, @Nullable android.telephony.data.DataCallResponse);
+ field public static final int RESULT_ERROR_BUSY = 3; // 0x3
+ field public static final int RESULT_ERROR_ILLEGAL_STATE = 4; // 0x4
+ field public static final int RESULT_ERROR_INVALID_ARG = 2; // 0x2
+ field public static final int RESULT_ERROR_UNSUPPORTED = 1; // 0x1
+ field public static final int RESULT_SUCCESS = 0; // 0x0
+ }
+
+ public abstract class QualifiedNetworksService extends android.app.Service {
+ ctor public QualifiedNetworksService();
+ method @NonNull public abstract android.telephony.data.QualifiedNetworksService.NetworkAvailabilityProvider onCreateNetworkAvailabilityProvider(int);
+ field public static final String QUALIFIED_NETWORKS_SERVICE_INTERFACE = "android.telephony.data.QualifiedNetworksService";
+ }
+
+ public abstract class QualifiedNetworksService.NetworkAvailabilityProvider implements java.lang.AutoCloseable {
+ ctor public QualifiedNetworksService.NetworkAvailabilityProvider(int);
+ method public abstract void close();
+ method public final int getSlotIndex();
+ method public final void updateQualifiedNetworkTypes(int, @NonNull java.util.List<java.lang.Integer>);
+ }
+
+}
+
+package android.telephony.euicc {
+
+ public final class DownloadableSubscription implements android.os.Parcelable {
+ method public java.util.List<android.telephony.UiccAccessRule> getAccessRules();
+ method @Nullable public String getCarrierName();
+ }
+
+ public static final class DownloadableSubscription.Builder {
+ ctor public DownloadableSubscription.Builder();
+ ctor public DownloadableSubscription.Builder(android.telephony.euicc.DownloadableSubscription);
+ method public android.telephony.euicc.DownloadableSubscription build();
+ method public android.telephony.euicc.DownloadableSubscription.Builder setAccessRules(java.util.List<android.telephony.UiccAccessRule>);
+ method public android.telephony.euicc.DownloadableSubscription.Builder setCarrierName(String);
+ method public android.telephony.euicc.DownloadableSubscription.Builder setConfirmationCode(String);
+ method public android.telephony.euicc.DownloadableSubscription.Builder setEncodedActivationCode(String);
+ }
+
+ public class EuiccCardManager {
+ method public void authenticateServer(String, String, byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+ method public void cancelSession(String, byte[], @android.telephony.euicc.EuiccCardManager.CancelReason int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+ method public void deleteProfile(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+ method public void disableProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+ method public void listNotifications(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>);
+ method public void loadBoundProfilePackage(String, byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+ method public void prepareDownload(String, @Nullable byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+ method public void removeNotificationFromList(String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+ method public void requestAllProfiles(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo[]>);
+ method public void requestDefaultSmdpAddress(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.String>);
+ method public void requestEuiccChallenge(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+ method public void requestEuiccInfo1(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+ method public void requestEuiccInfo2(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
+ method public void requestProfile(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
+ method public void requestRulesAuthTable(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccRulesAuthTable>);
+ method public void requestSmdsAddress(String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.String>);
+ method public void resetMemory(String, @android.telephony.euicc.EuiccCardManager.ResetOption int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+ method public void retrieveNotification(String, int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification>);
+ method public void retrieveNotificationList(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>);
+ method public void setDefaultSmdpAddress(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+ method public void setNickname(String, String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+ method public void switchToProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
+ field public static final int CANCEL_REASON_END_USER_REJECTED = 0; // 0x0
+ field public static final int CANCEL_REASON_POSTPONED = 1; // 0x1
+ field public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3; // 0x3
+ field public static final int CANCEL_REASON_TIMEOUT = 2; // 0x2
+ field public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 2; // 0x2
+ field public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1; // 0x1
+ field public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 4; // 0x4
+ field public static final int RESULT_CALLER_NOT_ALLOWED = -3; // 0xfffffffd
+ field public static final int RESULT_EUICC_NOT_FOUND = -2; // 0xfffffffe
+ field public static final int RESULT_OK = 0; // 0x0
+ field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff
+ }
+
+ @IntDef(prefix={"CANCEL_REASON_"}, value={android.telephony.euicc.EuiccCardManager.CANCEL_REASON_END_USER_REJECTED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_POSTPONED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_TIMEOUT, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_PPR_NOT_ALLOWED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.CancelReason {
+ }
+
+ @IntDef(flag=true, prefix={"RESET_OPTION_"}, value={android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.ResetOption {
+ }
+
+ public static interface EuiccCardManager.ResultCallback<T> {
+ method public void onComplete(int, T);
+ }
+
+ public class EuiccManager {
+ method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void continueOperation(android.content.Intent, android.os.Bundle);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(@NonNull android.app.PendingIntent);
+ method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void eraseSubscriptions(@android.telephony.euicc.EuiccCardManager.ResetOption int, @NonNull android.app.PendingIntent);
+ method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDefaultDownloadableSubscriptionList(android.app.PendingIntent);
+ method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent);
+ method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public int getOtaStatus();
+ method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public java.util.List<java.lang.String> getSupportedCountries();
+ method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public java.util.List<java.lang.String> getUnsupportedCountries();
+ method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public boolean isSupportedCountry(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void setSupportedCountries(@NonNull java.util.List<java.lang.String>);
+ method @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public void setUnsupportedCountries(@NonNull java.util.List<java.lang.String>);
+ field public static final String ACTION_DELETE_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.DELETE_SUBSCRIPTION_PRIVILEGED";
+ field @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) public static final String ACTION_OTA_STATUS_CHANGED = "android.telephony.euicc.action.OTA_STATUS_CHANGED";
+ field public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
+ field public static final String ACTION_RENAME_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.RENAME_SUBSCRIPTION_PRIVILEGED";
+ field public static final String ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED = "android.telephony.euicc.action.TOGGLE_SUBSCRIPTION_PRIVILEGED";
+ field public static final int EUICC_ACTIVATION_TYPE_ACCOUNT_REQUIRED = 4; // 0x4
+ field public static final int EUICC_ACTIVATION_TYPE_BACKUP = 2; // 0x2
+ field public static final int EUICC_ACTIVATION_TYPE_DEFAULT = 1; // 0x1
+ field public static final int EUICC_ACTIVATION_TYPE_TRANSFER = 3; // 0x3
+ field public static final int EUICC_OTA_FAILED = 2; // 0x2
+ field public static final int EUICC_OTA_IN_PROGRESS = 1; // 0x1
+ field public static final int EUICC_OTA_NOT_NEEDED = 4; // 0x4
+ field public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5; // 0x5
+ field public static final int EUICC_OTA_SUCCEEDED = 3; // 0x3
+ field public static final String EXTRA_ACTIVATION_TYPE = "android.telephony.euicc.extra.ACTIVATION_TYPE";
+ field public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS";
+ field public static final String EXTRA_ENABLE_SUBSCRIPTION = "android.telephony.euicc.extra.ENABLE_SUBSCRIPTION";
+ field public static final String EXTRA_FORCE_PROVISION = "android.telephony.euicc.extra.FORCE_PROVISION";
+ field public static final String EXTRA_FROM_SUBSCRIPTION_ID = "android.telephony.euicc.extra.FROM_SUBSCRIPTION_ID";
+ field public static final String EXTRA_PHYSICAL_SLOT_ID = "android.telephony.euicc.extra.PHYSICAL_SLOT_ID";
+ field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.euicc.extra.SUBSCRIPTION_ID";
+ field public static final String EXTRA_SUBSCRIPTION_NICKNAME = "android.telephony.euicc.extra.SUBSCRIPTION_NICKNAME";
+ }
+
+ @IntDef(prefix={"EUICC_OTA_"}, value={android.telephony.euicc.EuiccManager.EUICC_OTA_IN_PROGRESS, android.telephony.euicc.EuiccManager.EUICC_OTA_FAILED, android.telephony.euicc.EuiccManager.EUICC_OTA_SUCCEEDED, android.telephony.euicc.EuiccManager.EUICC_OTA_NOT_NEEDED, android.telephony.euicc.EuiccManager.EUICC_OTA_STATUS_UNAVAILABLE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccManager.OtaStatus {
+ }
+
+ public final class EuiccNotification implements android.os.Parcelable {
+ ctor public EuiccNotification(int, String, @android.telephony.euicc.EuiccNotification.Event int, @Nullable byte[]);
+ method public int describeContents();
+ method @Nullable public byte[] getData();
+ method @android.telephony.euicc.EuiccNotification.Event public int getEvent();
+ method public int getSeq();
+ method public String getTargetAddr();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @android.telephony.euicc.EuiccNotification.Event public static final int ALL_EVENTS = 15; // 0xf
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccNotification> CREATOR;
+ field public static final int EVENT_DELETE = 8; // 0x8
+ field public static final int EVENT_DISABLE = 4; // 0x4
+ field public static final int EVENT_ENABLE = 2; // 0x2
+ field public static final int EVENT_INSTALL = 1; // 0x1
+ }
+
+ @IntDef(flag=true, prefix={"EVENT_"}, value={android.telephony.euicc.EuiccNotification.EVENT_INSTALL, android.telephony.euicc.EuiccNotification.EVENT_ENABLE, android.telephony.euicc.EuiccNotification.EVENT_DISABLE, android.telephony.euicc.EuiccNotification.EVENT_DELETE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccNotification.Event {
+ }
+
+ public final class EuiccRulesAuthTable implements android.os.Parcelable {
+ method public int describeContents();
+ method public int findIndex(@android.service.euicc.EuiccProfileInfo.PolicyRule int, android.service.carrier.CarrierIdentifier);
+ method public boolean hasPolicyRuleFlag(int, @android.telephony.euicc.EuiccRulesAuthTable.PolicyRuleFlag int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.euicc.EuiccRulesAuthTable> CREATOR;
+ field public static final int POLICY_RULE_FLAG_CONSENT_REQUIRED = 1; // 0x1
+ }
+
+ public static final class EuiccRulesAuthTable.Builder {
+ ctor public EuiccRulesAuthTable.Builder(int);
+ method public android.telephony.euicc.EuiccRulesAuthTable.Builder add(int, java.util.List<android.service.carrier.CarrierIdentifier>, int);
+ method public android.telephony.euicc.EuiccRulesAuthTable build();
+ }
+
+ @IntDef(flag=true, prefix={"POLICY_RULE_FLAG_"}, value={android.telephony.euicc.EuiccRulesAuthTable.POLICY_RULE_FLAG_CONSENT_REQUIRED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccRulesAuthTable.PolicyRuleFlag {
+ }
+
+}
+
+package android.telephony.ims {
+
+ public final class ImsCallForwardInfo implements android.os.Parcelable {
+ ctor public ImsCallForwardInfo(int, int, int, int, @NonNull String, int);
+ method public int describeContents();
+ method public int getCondition();
+ method public String getNumber();
+ method public int getServiceClass();
+ method public int getStatus();
+ method public int getTimeSeconds();
+ method public int getToA();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CDIV_CF_REASON_ALL = 4; // 0x4
+ field public static final int CDIV_CF_REASON_ALL_CONDITIONAL = 5; // 0x5
+ field public static final int CDIV_CF_REASON_BUSY = 1; // 0x1
+ field public static final int CDIV_CF_REASON_NOT_LOGGED_IN = 6; // 0x6
+ field public static final int CDIV_CF_REASON_NOT_REACHABLE = 3; // 0x3
+ field public static final int CDIV_CF_REASON_NO_REPLY = 2; // 0x2
+ field public static final int CDIV_CF_REASON_UNCONDITIONAL = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallForwardInfo> CREATOR;
+ field public static final int STATUS_ACTIVE = 1; // 0x1
+ field public static final int STATUS_NOT_ACTIVE = 0; // 0x0
+ field public static final int TYPE_OF_ADDRESS_INTERNATIONAL = 145; // 0x91
+ field public static final int TYPE_OF_ADDRESS_UNKNOWN = 129; // 0x81
+ }
+
+ public final class ImsCallProfile implements android.os.Parcelable {
+ ctor public ImsCallProfile();
+ ctor public ImsCallProfile(int, int);
+ ctor public ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile);
+ method public int describeContents();
+ method public String getCallExtra(String);
+ method public String getCallExtra(String, String);
+ method public boolean getCallExtraBoolean(String);
+ method public boolean getCallExtraBoolean(String, boolean);
+ method public int getCallExtraInt(String);
+ method public int getCallExtraInt(String, int);
+ method public android.os.Bundle getCallExtras();
+ method public int getCallType();
+ method public static int getCallTypeFromVideoState(int);
+ method public int getCallerNumberVerificationStatus();
+ method public int getEmergencyCallRouting();
+ method public int getEmergencyServiceCategories();
+ method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
+ method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
+ method @NonNull public android.os.Bundle getProprietaryCallExtras();
+ method public int getRestrictCause();
+ method public int getServiceType();
+ method public static int getVideoStateFromCallType(int);
+ method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile);
+ method public boolean hasKnownUserIntentEmergency();
+ method public boolean isEmergencyCallTesting();
+ method public boolean isVideoCall();
+ method public boolean isVideoPaused();
+ method public static int presentationToOir(int);
+ method public void setCallExtra(String, String);
+ method public void setCallExtraBoolean(String, boolean);
+ method public void setCallExtraInt(String, int);
+ method public void setCallRestrictCause(int);
+ method public void setCallerNumberVerificationStatus(int);
+ method public void setEmergencyCallRouting(int);
+ method public void setEmergencyCallTesting(boolean);
+ method public void setEmergencyServiceCategories(int);
+ method public void setEmergencyUrns(@NonNull java.util.List<java.lang.String>);
+ method public void setHasKnownUserIntentEmergency(boolean);
+ method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
+ method public void updateCallType(android.telephony.ims.ImsCallProfile);
+ method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CALL_RESTRICT_CAUSE_DISABLED = 2; // 0x2
+ field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3
+ field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0
+ field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1
+ field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3
+ field public static final int CALL_TYPE_VOICE = 2; // 0x2
+ field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1
+ field public static final int CALL_TYPE_VS = 8; // 0x8
+ field public static final int CALL_TYPE_VS_RX = 10; // 0xa
+ field public static final int CALL_TYPE_VS_TX = 9; // 0x9
+ field public static final int CALL_TYPE_VT = 4; // 0x4
+ field public static final int CALL_TYPE_VT_NODIR = 7; // 0x7
+ field public static final int CALL_TYPE_VT_RX = 6; // 0x6
+ field public static final int CALL_TYPE_VT_TX = 5; // 0x5
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallProfile> CREATOR;
+ field public static final int DIALSTRING_NORMAL = 0; // 0x0
+ field public static final int DIALSTRING_SS_CONF = 1; // 0x1
+ field public static final int DIALSTRING_USSD = 2; // 0x2
+ field public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
+ field public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS = "android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS";
+ field public static final String EXTRA_CALL_DISCONNECT_CAUSE = "android.telephony.ims.extra.CALL_DISCONNECT_CAUSE";
+ field public static final String EXTRA_CALL_NETWORK_TYPE = "android.telephony.ims.extra.CALL_NETWORK_TYPE";
+ field @Deprecated public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
+ field public static final String EXTRA_CHILD_NUMBER = "ChildNum";
+ field public static final String EXTRA_CNA = "cna";
+ field public static final String EXTRA_CNAP = "cnap";
+ field public static final String EXTRA_CODEC = "Codec";
+ field public static final String EXTRA_DIALSTRING = "dialstring";
+ field public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
+ field public static final String EXTRA_EMERGENCY_CALL = "e_call";
+ field public static final String EXTRA_FORWARDED_NUMBER = "android.telephony.ims.extra.FORWARDED_NUMBER";
+ field public static final String EXTRA_IS_CALL_PULL = "CallPull";
+ field public static final String EXTRA_OI = "oi";
+ field public static final String EXTRA_OIR = "oir";
+ field public static final String EXTRA_REMOTE_URI = "remote_uri";
+ field public static final String EXTRA_USSD = "ussd";
+ field public static final int OIR_DEFAULT = 0; // 0x0
+ field public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2; // 0x2
+ field public static final int OIR_PRESENTATION_PAYPHONE = 4; // 0x4
+ field public static final int OIR_PRESENTATION_RESTRICTED = 1; // 0x1
+ field public static final int OIR_PRESENTATION_UNKNOWN = 3; // 0x3
+ field public static final int SERVICE_TYPE_EMERGENCY = 2; // 0x2
+ field public static final int SERVICE_TYPE_NONE = 0; // 0x0
+ field public static final int SERVICE_TYPE_NORMAL = 1; // 0x1
+ field public static final int VERIFICATION_STATUS_FAILED = 2; // 0x2
+ field public static final int VERIFICATION_STATUS_NOT_VERIFIED = 0; // 0x0
+ field public static final int VERIFICATION_STATUS_PASSED = 1; // 0x1
+ }
+
+ public class ImsCallSessionListener {
+ method public void callQualityChanged(@NonNull android.telephony.CallQuality);
+ method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+ method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+ method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState);
+ method @Deprecated public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo);
+ method @Deprecated public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo);
+ method public void callSessionHeld(android.telephony.ims.ImsCallProfile);
+ method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionInitiated(android.telephony.ims.ImsCallProfile);
+ method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionInviteParticipantsRequestDelivered();
+ method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
+ method @Deprecated public void callSessionMayHandover(int, int);
+ method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase);
+ method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+ method public void callSessionMultipartyStateChanged(boolean);
+ method public void callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile);
+ method public void callSessionRemoveParticipantsRequestDelivered();
+ method public void callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionResumed(android.telephony.ims.ImsCallProfile);
+ method public void callSessionRttAudioIndicatorChanged(@NonNull android.telephony.ims.ImsStreamMediaProfile);
+ method public void callSessionRttMessageReceived(String);
+ method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionRttModifyResponseReceived(int);
+ method public void callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification);
+ method public void callSessionTerminated(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionTtyModeReceived(int);
+ method public void callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionUpdated(android.telephony.ims.ImsCallProfile);
+ method public void callSessionUssdMessageReceived(int, String);
+ method public void onHandover(int, int, @Nullable android.telephony.ims.ImsReasonInfo);
+ method public void onHandoverFailed(int, int, @NonNull android.telephony.ims.ImsReasonInfo);
+ method public void onMayHandover(int, int);
+ }
+
+ public final class ImsConferenceState implements android.os.Parcelable {
+ method public int describeContents();
+ method public static int getConnectionStateForStatus(String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsConferenceState> CREATOR;
+ field public static final String DISPLAY_TEXT = "display-text";
+ field public static final String ENDPOINT = "endpoint";
+ field public static final String SIP_STATUS_CODE = "sipstatuscode";
+ field public static final String STATUS = "status";
+ field public static final String STATUS_ALERTING = "alerting";
+ field public static final String STATUS_CONNECTED = "connected";
+ field public static final String STATUS_CONNECT_FAIL = "connect-fail";
+ field public static final String STATUS_DIALING_IN = "dialing-in";
+ field public static final String STATUS_DIALING_OUT = "dialing-out";
+ field public static final String STATUS_DISCONNECTED = "disconnected";
+ field public static final String STATUS_DISCONNECTING = "disconnecting";
+ field public static final String STATUS_MUTED_VIA_FOCUS = "muted-via-focus";
+ field public static final String STATUS_ON_HOLD = "on-hold";
+ field public static final String STATUS_PENDING = "pending";
+ field public static final String STATUS_SEND_ONLY = "sendonly";
+ field public static final String STATUS_SEND_RECV = "sendrecv";
+ field public static final String USER = "user";
+ field public final java.util.HashMap<java.lang.String,android.os.Bundle> mParticipants;
+ }
+
+ public final class ImsException extends java.lang.Exception {
+ ctor public ImsException(@Nullable String);
+ ctor public ImsException(@Nullable String, int);
+ ctor public ImsException(@Nullable String, int, @Nullable Throwable);
+ }
+
+ public final class ImsExternalCallState implements android.os.Parcelable {
+ ctor public ImsExternalCallState(@NonNull String, @NonNull android.net.Uri, @Nullable android.net.Uri, boolean, int, int, boolean);
+ method public int describeContents();
+ method @NonNull public android.net.Uri getAddress();
+ method public int getCallId();
+ method public int getCallState();
+ method public int getCallType();
+ method @Nullable public android.net.Uri getLocalAddress();
+ method public boolean isCallHeld();
+ method public boolean isCallPullable();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CALL_STATE_CONFIRMED = 1; // 0x1
+ field public static final int CALL_STATE_TERMINATED = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
+ }
+
+ public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
+ method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(int, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(int, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean, int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingModeSetting(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
+ }
+
+ @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback {
+ ctor @Deprecated public ImsMmTelManager.RegistrationCallback();
+ }
+
+ public final class ImsReasonInfo implements android.os.Parcelable {
+ field public static final String EXTRA_MSG_SERVICE_NOT_AUTHORIZED = "Forbidden. Not Authorized for Service";
+ }
+
+ public class ImsService extends android.app.Service {
+ ctor public ImsService();
+ method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
+ method public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
+ method public void disableIms(int);
+ method public void enableIms(int);
+ method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+ method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+ method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
+ method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
+ method public void readyForFeatureCreation();
+ }
+
+ public final class ImsSsData implements android.os.Parcelable {
+ ctor public ImsSsData(int, int, int, int, int);
+ method public int describeContents();
+ method @Nullable public java.util.List<android.telephony.ims.ImsCallForwardInfo> getCallForwardInfo();
+ method public int getRequestType();
+ method public int getResult();
+ method public int getServiceClass();
+ method public int getServiceType();
+ method @NonNull public java.util.List<android.telephony.ims.ImsSsInfo> getSuppServiceInfo();
+ method public int getTeleserviceType();
+ method public boolean isTypeBarring();
+ method public boolean isTypeCf();
+ method public boolean isTypeClip();
+ method public boolean isTypeClir();
+ method public boolean isTypeColp();
+ method public boolean isTypeColr();
+ method public boolean isTypeCw();
+ method public boolean isTypeIcb();
+ method public boolean isTypeInterrogation();
+ method public boolean isTypeUnConditional();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsData> CREATOR;
+ field public static final int RESULT_SUCCESS = 0; // 0x0
+ field public static final int SERVICE_CLASS_DATA = 2; // 0x2
+ field public static final int SERVICE_CLASS_DATA_CIRCUIT_ASYNC = 32; // 0x20
+ field public static final int SERVICE_CLASS_DATA_CIRCUIT_SYNC = 16; // 0x10
+ field public static final int SERVICE_CLASS_DATA_PACKET_ACCESS = 64; // 0x40
+ field public static final int SERVICE_CLASS_DATA_PAD = 128; // 0x80
+ field public static final int SERVICE_CLASS_FAX = 4; // 0x4
+ field public static final int SERVICE_CLASS_NONE = 0; // 0x0
+ field public static final int SERVICE_CLASS_SMS = 8; // 0x8
+ field public static final int SERVICE_CLASS_VOICE = 1; // 0x1
+ field public static final int SS_ACTIVATION = 0; // 0x0
+ field public static final int SS_ALL_BARRING = 18; // 0x12
+ field public static final int SS_ALL_DATA_TELESERVICES = 3; // 0x3
+ field public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5; // 0x5
+ field public static final int SS_ALL_TELESEVICES = 1; // 0x1
+ field public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0; // 0x0
+ field public static final int SS_BAIC = 16; // 0x10
+ field public static final int SS_BAIC_ROAMING = 17; // 0x11
+ field public static final int SS_BAOC = 13; // 0xd
+ field public static final int SS_BAOIC = 14; // 0xe
+ field public static final int SS_BAOIC_EXC_HOME = 15; // 0xf
+ field public static final int SS_CFU = 0; // 0x0
+ field public static final int SS_CFUT = 6; // 0x6
+ field public static final int SS_CF_ALL = 4; // 0x4
+ field public static final int SS_CF_ALL_CONDITIONAL = 5; // 0x5
+ field public static final int SS_CF_BUSY = 1; // 0x1
+ field public static final int SS_CF_NOT_REACHABLE = 3; // 0x3
+ field public static final int SS_CF_NO_REPLY = 2; // 0x2
+ field public static final int SS_CLIP = 7; // 0x7
+ field public static final int SS_CLIR = 8; // 0x8
+ field public static final int SS_CNAP = 11; // 0xb
+ field public static final int SS_COLP = 9; // 0x9
+ field public static final int SS_COLR = 10; // 0xa
+ field public static final int SS_DEACTIVATION = 1; // 0x1
+ field public static final int SS_ERASURE = 4; // 0x4
+ field public static final int SS_INCOMING_BARRING = 20; // 0x14
+ field public static final int SS_INCOMING_BARRING_ANONYMOUS = 22; // 0x16
+ field public static final int SS_INCOMING_BARRING_DN = 21; // 0x15
+ field public static final int SS_INTERROGATION = 2; // 0x2
+ field public static final int SS_OUTGOING_BARRING = 19; // 0x13
+ field public static final int SS_REGISTRATION = 3; // 0x3
+ field public static final int SS_SMS_SERVICES = 4; // 0x4
+ field public static final int SS_TELEPHONY = 2; // 0x2
+ field public static final int SS_WAIT = 12; // 0xc
+ }
+
+ public static final class ImsSsData.Builder {
+ ctor public ImsSsData.Builder(int, int, int, int, int);
+ method @NonNull public android.telephony.ims.ImsSsData build();
+ method @NonNull public android.telephony.ims.ImsSsData.Builder setCallForwardingInfo(@NonNull java.util.List<android.telephony.ims.ImsCallForwardInfo>);
+ method @NonNull public android.telephony.ims.ImsSsData.Builder setSuppServiceInfo(@NonNull java.util.List<android.telephony.ims.ImsSsInfo>);
+ }
+
+ public final class ImsSsInfo implements android.os.Parcelable {
+ ctor @Deprecated public ImsSsInfo(int, @Nullable String);
+ method public int describeContents();
+ method public int getClirInterrogationStatus();
+ method public int getClirOutgoingState();
+ method @Deprecated public String getIcbNum();
+ method @Nullable public String getIncomingCommunicationBarringNumber();
+ method public int getProvisionStatus();
+ method public int getStatus();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CLIR_OUTGOING_DEFAULT = 0; // 0x0
+ field public static final int CLIR_OUTGOING_INVOCATION = 1; // 0x1
+ field public static final int CLIR_OUTGOING_SUPPRESSION = 2; // 0x2
+ field public static final int CLIR_STATUS_NOT_PROVISIONED = 0; // 0x0
+ field public static final int CLIR_STATUS_PROVISIONED_PERMANENT = 1; // 0x1
+ field public static final int CLIR_STATUS_TEMPORARILY_ALLOWED = 4; // 0x4
+ field public static final int CLIR_STATUS_TEMPORARILY_RESTRICTED = 3; // 0x3
+ field public static final int CLIR_STATUS_UNKNOWN = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR;
+ field public static final int DISABLED = 0; // 0x0
+ field public static final int ENABLED = 1; // 0x1
+ field public static final int NOT_REGISTERED = -1; // 0xffffffff
+ field public static final int SERVICE_NOT_PROVISIONED = 0; // 0x0
+ field public static final int SERVICE_PROVISIONED = 1; // 0x1
+ field public static final int SERVICE_PROVISIONING_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public static final class ImsSsInfo.Builder {
+ ctor public ImsSsInfo.Builder(int);
+ method @NonNull public android.telephony.ims.ImsSsInfo build();
+ method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirInterrogationStatus(int);
+ method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirOutgoingState(int);
+ method @NonNull public android.telephony.ims.ImsSsInfo.Builder setIncomingCommunicationBarringNumber(@NonNull String);
+ method @NonNull public android.telephony.ims.ImsSsInfo.Builder setProvisionStatus(int);
+ }
+
+ public final class ImsStreamMediaProfile implements android.os.Parcelable {
+ ctor public ImsStreamMediaProfile(int, int, int, int, int);
+ method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile);
+ method public int describeContents();
+ method public int getAudioDirection();
+ method public int getAudioQuality();
+ method public int getRttMode();
+ method public int getVideoDirection();
+ method public int getVideoQuality();
+ method public boolean isReceivingRttAudio();
+ method public boolean isRttCall();
+ method public void setReceivingRttAudio(boolean);
+ method public void setRttMode(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int AUDIO_QUALITY_AMR = 1; // 0x1
+ field public static final int AUDIO_QUALITY_AMR_WB = 2; // 0x2
+ field public static final int AUDIO_QUALITY_EVRC = 4; // 0x4
+ field public static final int AUDIO_QUALITY_EVRC_B = 5; // 0x5
+ field public static final int AUDIO_QUALITY_EVRC_NW = 7; // 0x7
+ field public static final int AUDIO_QUALITY_EVRC_WB = 6; // 0x6
+ field public static final int AUDIO_QUALITY_EVS_FB = 20; // 0x14
+ field public static final int AUDIO_QUALITY_EVS_NB = 17; // 0x11
+ field public static final int AUDIO_QUALITY_EVS_SWB = 19; // 0x13
+ field public static final int AUDIO_QUALITY_EVS_WB = 18; // 0x12
+ field public static final int AUDIO_QUALITY_G711A = 13; // 0xd
+ field public static final int AUDIO_QUALITY_G711AB = 15; // 0xf
+ field public static final int AUDIO_QUALITY_G711U = 11; // 0xb
+ field public static final int AUDIO_QUALITY_G722 = 14; // 0xe
+ field public static final int AUDIO_QUALITY_G723 = 12; // 0xc
+ field public static final int AUDIO_QUALITY_G729 = 16; // 0x10
+ field public static final int AUDIO_QUALITY_GSM_EFR = 8; // 0x8
+ field public static final int AUDIO_QUALITY_GSM_FR = 9; // 0x9
+ field public static final int AUDIO_QUALITY_GSM_HR = 10; // 0xa
+ field public static final int AUDIO_QUALITY_NONE = 0; // 0x0
+ field public static final int AUDIO_QUALITY_QCELP13K = 3; // 0x3
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsStreamMediaProfile> CREATOR;
+ field public static final int DIRECTION_INACTIVE = 0; // 0x0
+ field public static final int DIRECTION_INVALID = -1; // 0xffffffff
+ field public static final int DIRECTION_RECEIVE = 1; // 0x1
+ field public static final int DIRECTION_SEND = 2; // 0x2
+ field public static final int DIRECTION_SEND_RECEIVE = 3; // 0x3
+ field public static final int RTT_MODE_DISABLED = 0; // 0x0
+ field public static final int RTT_MODE_FULL = 1; // 0x1
+ field public static final int VIDEO_QUALITY_NONE = 0; // 0x0
+ field public static final int VIDEO_QUALITY_QCIF = 1; // 0x1
+ field public static final int VIDEO_QUALITY_QVGA_LANDSCAPE = 2; // 0x2
+ field public static final int VIDEO_QUALITY_QVGA_PORTRAIT = 4; // 0x4
+ field public static final int VIDEO_QUALITY_VGA_LANDSCAPE = 8; // 0x8
+ field public static final int VIDEO_QUALITY_VGA_PORTRAIT = 16; // 0x10
+ }
+
+ public final class ImsSuppServiceNotification implements android.os.Parcelable {
+ ctor public ImsSuppServiceNotification(int, int, int, int, String, String[]);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSuppServiceNotification> CREATOR;
+ field public final int code;
+ field public final String[] history;
+ field public final int index;
+ field public final int notificationType;
+ field public final String number;
+ field public final int type;
+ }
+
+ public class ImsUtListener {
+ method public void onLineIdentificationSupplementaryServiceResponse(int, @NonNull android.telephony.ims.ImsSsInfo);
+ method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData);
+ method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]);
+ method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]);
+ method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]);
+ method @Deprecated public void onUtConfigurationQueried(int, android.os.Bundle);
+ method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo);
+ method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo);
+ method public void onUtConfigurationUpdated(int);
+ field @Deprecated public static final String BUNDLE_KEY_CLIR = "queryClir";
+ field @Deprecated public static final String BUNDLE_KEY_SSINFO = "imsSsInfo";
+ }
+
+ public abstract class ImsVideoCallProvider {
+ ctor public ImsVideoCallProvider();
+ method public void changeCallDataUsage(long);
+ method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities);
+ method public void changePeerDimensions(int, int);
+ method public void changeVideoQuality(int);
+ method public void handleCallSessionEvent(int);
+ method public abstract void onRequestCallDataUsage();
+ method public abstract void onRequestCameraCapabilities();
+ method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile);
+ method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile);
+ method public abstract void onSetCamera(String);
+ method public void onSetCamera(String, int);
+ method public abstract void onSetDeviceOrientation(int);
+ method public abstract void onSetDisplaySurface(android.view.Surface);
+ method public abstract void onSetPauseImage(android.net.Uri);
+ method public abstract void onSetPreviewSurface(android.view.Surface);
+ method public abstract void onSetZoom(float);
+ method public void receiveSessionModifyRequest(android.telecom.VideoProfile);
+ method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
+ }
+
+ public class ProvisioningManager {
+ method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
+ field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
+ field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
+ field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0
+ field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1
+ field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC";
+ field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY";
+ }
+
+ public static class ProvisioningManager.Callback {
+ ctor public ProvisioningManager.Callback();
+ method public void onProvisioningIntChanged(int, int);
+ method public void onProvisioningStringChanged(int, @NonNull String);
+ }
+
+ public class RcsUceAdapter {
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
+ }
+
+}
+
+package android.telephony.ims.feature {
+
+ public final class CapabilityChangeRequest implements android.os.Parcelable {
+ method public void addCapabilitiesToDisableForTech(int, int);
+ method public void addCapabilitiesToEnableForTech(int, int);
+ method public int describeContents();
+ method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToDisable();
+ method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToEnable();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.feature.CapabilityChangeRequest> CREATOR;
+ }
+
+ public static class CapabilityChangeRequest.CapabilityPair {
+ ctor public CapabilityChangeRequest.CapabilityPair(int, int);
+ method public int getCapability();
+ method public int getRadioTech();
+ }
+
+ public abstract class ImsFeature {
+ ctor public ImsFeature();
+ method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method public int getFeatureState();
+ method public final int getSlotIndex();
+ method public abstract void onFeatureReady();
+ method public abstract void onFeatureRemoved();
+ method public final void setFeatureState(int);
+ field public static final int CAPABILITY_ERROR_GENERIC = -1; // 0xffffffff
+ field public static final int CAPABILITY_SUCCESS = 0; // 0x0
+ field public static final int FEATURE_EMERGENCY_MMTEL = 0; // 0x0
+ field public static final int FEATURE_MMTEL = 1; // 0x1
+ field public static final int FEATURE_RCS = 2; // 0x2
+ field public static final int STATE_INITIALIZING = 1; // 0x1
+ field public static final int STATE_READY = 2; // 0x2
+ field public static final int STATE_UNAVAILABLE = 0; // 0x0
+ }
+
+ @Deprecated public static class ImsFeature.Capabilities {
+ field @Deprecated protected int mCapabilities;
+ }
+
+ protected static class ImsFeature.CapabilityCallbackProxy {
+ method public void onChangeCapabilityConfigurationError(int, int, int);
+ }
+
+ public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
+ ctor public MmTelFeature();
+ method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
+ method @Nullable public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(@NonNull android.telephony.ims.ImsCallProfile);
+ method @NonNull public android.telephony.ims.stub.ImsEcbmImplBase getEcbm();
+ method @NonNull public android.telephony.ims.stub.ImsMultiEndpointImplBase getMultiEndpoint();
+ method @NonNull public android.telephony.ims.stub.ImsSmsImplBase getSmsImplementation();
+ method @NonNull public android.telephony.ims.stub.ImsUtImplBase getUt();
+ method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
+ method public final void notifyIncomingCall(@NonNull android.telephony.ims.stub.ImsCallSessionImplBase, @NonNull android.os.Bundle);
+ method public final void notifyRejectedCall(@NonNull android.telephony.ims.ImsCallProfile, @NonNull android.telephony.ims.ImsReasonInfo);
+ method public final void notifyVoiceMessageCountUpdate(int);
+ method public void onFeatureReady();
+ method public void onFeatureRemoved();
+ method public boolean queryCapabilityConfiguration(int, int);
+ method @NonNull public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
+ method public void setUiTtyMode(int, @Nullable android.os.Message);
+ method public int shouldProcessCall(@NonNull String[]);
+ field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
+ field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
+ field public static final int PROCESS_CALL_CSFB = 1; // 0x1
+ field public static final int PROCESS_CALL_IMS = 0; // 0x0
+ }
+
+ public static class MmTelFeature.MmTelCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities {
+ ctor public MmTelFeature.MmTelCapabilities();
+ ctor @Deprecated public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities);
+ ctor public MmTelFeature.MmTelCapabilities(int);
+ method public final void addCapabilities(int);
+ method public final boolean isCapable(int);
+ method public final void removeCapabilities(int);
+ }
+
+ public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
+ ctor public RcsFeature();
+ method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method public void onFeatureReady();
+ method public void onFeatureRemoved();
+ }
+
+}
+
+package android.telephony.ims.stub {
+
+ public class ImsCallSessionImplBase implements java.lang.AutoCloseable {
+ ctor public ImsCallSessionImplBase();
+ method public void accept(int, android.telephony.ims.ImsStreamMediaProfile);
+ method public void close();
+ method public void deflect(String);
+ method public void extendToConference(String[]);
+ method public String getCallId();
+ method public android.telephony.ims.ImsCallProfile getCallProfile();
+ method public android.telephony.ims.ImsVideoCallProvider getImsVideoCallProvider();
+ method public android.telephony.ims.ImsCallProfile getLocalCallProfile();
+ method public String getProperty(String);
+ method public android.telephony.ims.ImsCallProfile getRemoteCallProfile();
+ method public int getState();
+ method public void hold(android.telephony.ims.ImsStreamMediaProfile);
+ method public void inviteParticipants(String[]);
+ method public boolean isInCall();
+ method public boolean isMultiparty();
+ method public void merge();
+ method public void reject(int);
+ method public void removeParticipants(String[]);
+ method public void resume(android.telephony.ims.ImsStreamMediaProfile);
+ method public void sendDtmf(char, android.os.Message);
+ method public void sendRttMessage(String);
+ method public void sendRttModifyRequest(android.telephony.ims.ImsCallProfile);
+ method public void sendRttModifyResponse(boolean);
+ method public void sendUssd(String);
+ method public void setListener(android.telephony.ims.ImsCallSessionListener);
+ method public void setMute(boolean);
+ method public void start(String, android.telephony.ims.ImsCallProfile);
+ method public void startConference(String[], android.telephony.ims.ImsCallProfile);
+ method public void startDtmf(char);
+ method public void stopDtmf();
+ method public void terminate(int);
+ method public void update(int, android.telephony.ims.ImsStreamMediaProfile);
+ field public static final int USSD_MODE_NOTIFY = 0; // 0x0
+ field public static final int USSD_MODE_REQUEST = 1; // 0x1
+ }
+
+ public static class ImsCallSessionImplBase.State {
+ method public static String toString(int);
+ field public static final int ESTABLISHED = 4; // 0x4
+ field public static final int ESTABLISHING = 3; // 0x3
+ field public static final int IDLE = 0; // 0x0
+ field public static final int INITIATED = 1; // 0x1
+ field public static final int INVALID = -1; // 0xffffffff
+ field public static final int NEGOTIATING = 2; // 0x2
+ field public static final int REESTABLISHING = 6; // 0x6
+ field public static final int RENEGOTIATING = 5; // 0x5
+ field public static final int TERMINATED = 8; // 0x8
+ field public static final int TERMINATING = 7; // 0x7
+ }
+
+ public class ImsConfigImplBase {
+ ctor public ImsConfigImplBase();
+ method public int getConfigInt(int);
+ method public String getConfigString(int);
+ method public final void notifyProvisionedValueChanged(int, int);
+ method public final void notifyProvisionedValueChanged(int, String);
+ method public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
+ method public int setConfig(int, int);
+ method public int setConfig(int, String);
+ field public static final int CONFIG_RESULT_FAILED = 1; // 0x1
+ field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0
+ field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public class ImsEcbmImplBase {
+ ctor public ImsEcbmImplBase();
+ method public final void enteredEcbm();
+ method public void exitEmergencyCallbackMode();
+ method public final void exitedEcbm();
+ }
+
+ public final class ImsFeatureConfiguration implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.util.Set<android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair> getServiceFeatures();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR;
+ }
+
+ public static class ImsFeatureConfiguration.Builder {
+ ctor public ImsFeatureConfiguration.Builder();
+ method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int, int);
+ method public android.telephony.ims.stub.ImsFeatureConfiguration build();
+ }
+
+ public static final class ImsFeatureConfiguration.FeatureSlotPair {
+ ctor public ImsFeatureConfiguration.FeatureSlotPair(int, int);
+ field public final int featureType;
+ field public final int slotId;
+ }
+
+ public class ImsMultiEndpointImplBase {
+ ctor public ImsMultiEndpointImplBase();
+ method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>);
+ method public void requestImsExternalCallStateInfo();
+ }
+
+ public class ImsRegistrationImplBase {
+ ctor public ImsRegistrationImplBase();
+ method public final void onDeregistered(android.telephony.ims.ImsReasonInfo);
+ method public final void onRegistered(int);
+ method public final void onRegistering(int);
+ method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]);
+ method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo);
+ field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
+ field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
+ field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
+ }
+
+ public class ImsSmsImplBase {
+ ctor public ImsSmsImplBase();
+ method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int);
+ method public void acknowledgeSmsReport(int, @IntRange(from=0, to=65535) int, int);
+ method public String getSmsFormat();
+ method public void onReady();
+ method @Deprecated public final void onSendSmsResult(int, @IntRange(from=0, to=65535) int, int, int) throws java.lang.RuntimeException;
+ method public final void onSendSmsResultError(int, @IntRange(from=0, to=65535) int, int, int, int) throws java.lang.RuntimeException;
+ method public final void onSendSmsResultSuccess(int, @IntRange(from=0, to=65535) int) throws java.lang.RuntimeException;
+ method public final void onSmsReceived(int, String, byte[]) throws java.lang.RuntimeException;
+ method @Deprecated public final void onSmsStatusReportReceived(int, @IntRange(from=0, to=65535) int, String, byte[]) throws java.lang.RuntimeException;
+ method public final void onSmsStatusReportReceived(int, String, byte[]) throws java.lang.RuntimeException;
+ method public void sendSms(int, @IntRange(from=0, to=65535) int, String, String, boolean, byte[]);
+ field public static final int DELIVER_STATUS_ERROR_GENERIC = 2; // 0x2
+ field public static final int DELIVER_STATUS_ERROR_NO_MEMORY = 3; // 0x3
+ field public static final int DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED = 4; // 0x4
+ field public static final int DELIVER_STATUS_OK = 1; // 0x1
+ field public static final int RESULT_NO_NETWORK_ERROR = -1; // 0xffffffff
+ field public static final int SEND_STATUS_ERROR = 2; // 0x2
+ field public static final int SEND_STATUS_ERROR_FALLBACK = 4; // 0x4
+ field public static final int SEND_STATUS_ERROR_RETRY = 3; // 0x3
+ field public static final int SEND_STATUS_OK = 1; // 0x1
+ field public static final int STATUS_REPORT_STATUS_ERROR = 2; // 0x2
+ field public static final int STATUS_REPORT_STATUS_OK = 1; // 0x1
+ }
+
+ public class ImsUtImplBase {
+ ctor public ImsUtImplBase();
+ method public void close();
+ method public int queryCallBarring(int);
+ method public int queryCallBarringForServiceClass(int, int);
+ method public int queryCallForward(int, String);
+ method public int queryCallWaiting();
+ method public int queryClip();
+ method public int queryClir();
+ method public int queryColp();
+ method public int queryColr();
+ method public void setListener(android.telephony.ims.ImsUtListener);
+ method public int transact(android.os.Bundle);
+ method public int updateCallBarring(int, int, String[]);
+ method public int updateCallBarringForServiceClass(int, int, String[], int);
+ method public int updateCallForward(int, int, String, int, int);
+ method public int updateCallWaiting(boolean, int);
+ method public int updateClip(boolean);
+ method public int updateClir(int);
+ method public int updateColp(boolean);
+ method public int updateColr(int);
+ }
+
+}
+
+package android.telephony.mbms {
+
+ public static class DownloadRequest.Builder {
+ method public android.telephony.mbms.DownloadRequest.Builder setServiceId(String);
+ }
+
+ public final class FileInfo implements android.os.Parcelable {
+ ctor public FileInfo(android.net.Uri, String);
+ }
+
+ public final class FileServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable {
+ ctor public FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>);
+ }
+
+ public class MbmsDownloadReceiver extends android.content.BroadcastReceiver {
+ field public static final int RESULT_APP_NOTIFICATION_ERROR = 6; // 0x6
+ field public static final int RESULT_BAD_TEMP_FILE_ROOT = 3; // 0x3
+ field public static final int RESULT_DOWNLOAD_FINALIZATION_ERROR = 4; // 0x4
+ field public static final int RESULT_INVALID_ACTION = 1; // 0x1
+ field public static final int RESULT_MALFORMED_INTENT = 2; // 0x2
+ field public static final int RESULT_OK = 0; // 0x0
+ field public static final int RESULT_TEMP_FILE_GENERATION_ERROR = 5; // 0x5
+ }
+
+ public final class StreamingServiceInfo extends android.telephony.mbms.ServiceInfo implements android.os.Parcelable {
+ ctor public StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date);
+ }
+
+ public final class UriPathPair implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.net.Uri getContentUri();
+ method public android.net.Uri getFilePathUri();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.mbms.UriPathPair> CREATOR;
+ }
+
+}
+
+package android.telephony.mbms.vendor {
+
+ public class MbmsDownloadServiceBase extends android.os.Binder implements android.os.IInterface {
+ ctor public MbmsDownloadServiceBase();
+ method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
+ method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
+ method public android.os.IBinder asBinder();
+ method public int cancelDownload(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
+ method public void dispose(int) throws android.os.RemoteException;
+ method public int download(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
+ method public int initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) throws android.os.RemoteException;
+ method @NonNull public java.util.List<android.telephony.mbms.DownloadRequest> listPendingDownloads(int) throws android.os.RemoteException;
+ method public void onAppCallbackDied(int, int);
+ method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+ method public int removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
+ method public int removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
+ method public int requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) throws android.os.RemoteException;
+ method public int requestUpdateFileServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException;
+ method public int resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) throws android.os.RemoteException;
+ method public int setTempFileRootDirectory(int, String) throws android.os.RemoteException;
+ }
+
+ public class MbmsGroupCallServiceBase extends android.app.Service {
+ ctor public MbmsGroupCallServiceBase();
+ method public void dispose(int) throws android.os.RemoteException;
+ method public int initialize(@NonNull android.telephony.mbms.MbmsGroupCallSessionCallback, int) throws android.os.RemoteException;
+ method public void onAppCallbackDied(int, int);
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public int startGroupCall(int, long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>, @NonNull android.telephony.mbms.GroupCallCallback);
+ method public void stopGroupCall(int, long);
+ method public void updateGroupCall(int, long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>);
+ }
+
+ public class MbmsStreamingServiceBase extends android.os.Binder implements android.os.IInterface {
+ ctor public MbmsStreamingServiceBase();
+ method public android.os.IBinder asBinder();
+ method public void dispose(int) throws android.os.RemoteException;
+ method @Nullable public android.net.Uri getPlaybackUri(int, String) throws android.os.RemoteException;
+ method public int initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int) throws android.os.RemoteException;
+ method public void onAppCallbackDied(int, int);
+ method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+ method public int requestUpdateStreamingServices(int, java.util.List<java.lang.String>) throws android.os.RemoteException;
+ method public int startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback) throws android.os.RemoteException;
+ method public void stopStreaming(int, String) throws android.os.RemoteException;
+ }
+
+ public class VendorUtils {
+ ctor public VendorUtils();
+ method public static android.content.ComponentName getAppReceiverFromPackageName(android.content.Context, String);
+ field public static final String ACTION_CLEANUP = "android.telephony.mbms.action.CLEANUP";
+ field public static final String ACTION_DOWNLOAD_RESULT_INTERNAL = "android.telephony.mbms.action.DOWNLOAD_RESULT_INTERNAL";
+ field public static final String ACTION_FILE_DESCRIPTOR_REQUEST = "android.telephony.mbms.action.FILE_DESCRIPTOR_REQUEST";
+ field public static final String EXTRA_FD_COUNT = "android.telephony.mbms.extra.FD_COUNT";
+ field public static final String EXTRA_FINAL_URI = "android.telephony.mbms.extra.FINAL_URI";
+ field public static final String EXTRA_FREE_URI_LIST = "android.telephony.mbms.extra.FREE_URI_LIST";
+ field public static final String EXTRA_PAUSED_LIST = "android.telephony.mbms.extra.PAUSED_LIST";
+ field public static final String EXTRA_PAUSED_URI_LIST = "android.telephony.mbms.extra.PAUSED_URI_LIST";
+ field public static final String EXTRA_SERVICE_ID = "android.telephony.mbms.extra.SERVICE_ID";
+ field public static final String EXTRA_TEMP_FILES_IN_USE = "android.telephony.mbms.extra.TEMP_FILES_IN_USE";
+ field public static final String EXTRA_TEMP_FILE_ROOT = "android.telephony.mbms.extra.TEMP_FILE_ROOT";
+ field public static final String EXTRA_TEMP_LIST = "android.telephony.mbms.extra.TEMP_LIST";
+ }
+
+}
+
diff --git a/telephony/api/system-removed.txt b/telephony/api/system-removed.txt
new file mode 100644
index 0000000..ae46075
--- /dev/null
+++ b/telephony/api/system-removed.txt
@@ -0,0 +1,19 @@
+// Signature format: 2.0
+package android.telephony {
+
+ public class TelephonyManager {
+ method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void answerRingingCall();
+ method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public boolean endCall();
+ method @Deprecated public void silenceRinger();
+ }
+
+}
+
+package android.telephony.data {
+
+ public final class DataCallResponse implements android.os.Parcelable {
+ ctor public DataCallResponse(int, int, int, int, int, @Nullable String, @Nullable java.util.List<android.net.LinkAddress>, @Nullable java.util.List<java.net.InetAddress>, @Nullable java.util.List<java.net.InetAddress>, @Nullable java.util.List<java.net.InetAddress>, int);
+ }
+
+}
+
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index b897725..f0f9721 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -437,8 +437,9 @@
/**
* Returns whether the caller can read phone numbers.
*
- * <p>Besides apps with the ability to read phone state per {@link #checkReadPhoneState}, the
- * default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS can also read phone numbers.
+ * <p>Besides apps with the ability to read phone state per {@link #checkReadPhoneState}
+ * (only prior to R), the default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS
+ * can also read phone numbers.
*/
public static boolean checkCallingOrSelfReadPhoneNumber(
Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
@@ -451,8 +452,9 @@
/**
* Returns whether the caller can read phone numbers.
*
- * <p>Besides apps with the ability to read phone state per {@link #checkReadPhoneState}, the
- * default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS can also read phone numbers.
+ * <p>Besides apps with the ability to read phone state per {@link #checkReadPhoneState}
+ * (only prior to R), the default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS
+ * can also read phone numbers.
*/
@VisibleForTesting
public static boolean checkReadPhoneNumber(
@@ -468,12 +470,15 @@
// NOTE(b/73308711): If an app has one of the following AppOps bits explicitly revoked, they
// will be denied access, even if they have another permission and AppOps bit if needed.
- // First, check if we can read the phone state.
+ // First, check if we can read the phone state and the SDK version is below R.
try {
- return checkReadPhoneState(
- context, subId, pid, uid, callingPackage, callingFeatureId,
- message);
- } catch (SecurityException readPhoneStateSecurityException) {
+ ApplicationInfo info = context.getPackageManager().getApplicationInfoAsUser(
+ callingPackage, 0, UserHandle.getUserHandleForUid(Binder.getCallingUid()));
+ if (info.targetSdkVersion <= Build.VERSION_CODES.Q) {
+ return checkReadPhoneState(
+ context, subId, pid, uid, callingPackage, callingFeatureId, message);
+ }
+ } catch (SecurityException | PackageManager.NameNotFoundException e) {
}
// Can be read with READ_SMS too.
try {
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index dcd4eb5..b8a74d2 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -571,6 +571,19 @@
public @interface PreciseDisconnectCauses {
}
+ /**
+ * Carrier Privilege Status.
+ */
+ @IntDef(prefix = { "CARRIER_PRIVILEGE_STATUS_" }, value = {
+ TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS,
+ TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS,
+ TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED,
+ TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CarrierPrivilegeStatus {
+ }
+
@IntDef({
Connection.AUDIO_CODEC_NONE,
Connection.AUDIO_CODEC_AMR,
@@ -598,48 +611,6 @@
}
/**
- * Call forwarding function status
- */
- @IntDef(prefix = { "STATUS_" }, value = {
- CallForwardingInfo.STATUS_ACTIVE,
- CallForwardingInfo.STATUS_INACTIVE,
- CallForwardingInfo.STATUS_UNKNOWN_ERROR,
- CallForwardingInfo.STATUS_NOT_SUPPORTED,
- CallForwardingInfo.STATUS_FDN_CHECK_FAILURE
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface CallForwardingStatus {
- }
-
- /**
- * Call forwarding reason types
- */
- @IntDef(flag = true, prefix = { "REASON_" }, value = {
- CallForwardingInfo.REASON_UNCONDITIONAL,
- CallForwardingInfo.REASON_BUSY,
- CallForwardingInfo.REASON_NO_REPLY,
- CallForwardingInfo.REASON_NOT_REACHABLE,
- CallForwardingInfo.REASON_ALL,
- CallForwardingInfo.REASON_ALL_CONDITIONAL
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface CallForwardingReason {
- }
-
- /**
- * Call waiting function status
- */
- @IntDef(prefix = { "CALL_WAITING_STATUS_" }, value = {
- TelephonyManager.CALL_WAITING_STATUS_ACTIVE,
- TelephonyManager.CALL_WAITING_STATUS_INACTIVE,
- TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED,
- TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface CallWaitingStatus {
- }
-
- /**
* UICC SIM Application Types
*/
@IntDef(prefix = { "APPTYPE_" }, value = {
diff --git a/telephony/java/android/telephony/CallForwardingInfo.java b/telephony/java/android/telephony/CallForwardingInfo.java
index 1dd7539..7e777fa 100644
--- a/telephony/java/android/telephony/CallForwardingInfo.java
+++ b/telephony/java/android/telephony/CallForwardingInfo.java
@@ -15,24 +15,24 @@
*/
package android.telephony;
+
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
-import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Annotation.CallForwardingReason;
-import android.telephony.Annotation.CallForwardingStatus;
import com.android.telephony.Rlog;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
* Defines the call forwarding information.
* @hide
*/
-@SystemApi
public final class CallForwardingInfo implements Parcelable {
private static final String TAG = "CallForwardingInfo";
@@ -41,7 +41,6 @@
*
* @hide
*/
- @SystemApi
public static final int STATUS_INACTIVE = 0;
/**
@@ -49,7 +48,6 @@
*
* @hide
*/
- @SystemApi
public static final int STATUS_ACTIVE = 1;
/**
@@ -58,7 +56,6 @@
*
* @hide
*/
- @SystemApi
public static final int STATUS_FDN_CHECK_FAILURE = 2;
/**
@@ -66,7 +63,6 @@
*
* @hide
*/
- @SystemApi
public static final int STATUS_UNKNOWN_ERROR = 3;
/**
@@ -74,7 +70,6 @@
*
* @hide
*/
- @SystemApi
public static final int STATUS_NOT_SUPPORTED = 4;
/**
@@ -83,7 +78,6 @@
* and conditions +CCFC
* @hide
*/
- @SystemApi
public static final int REASON_UNCONDITIONAL = 0;
/**
@@ -92,7 +86,6 @@
* and conditions +CCFC
* @hide
*/
- @SystemApi
public static final int REASON_BUSY = 1;
/**
@@ -101,7 +94,6 @@
* and conditions +CCFC
* @hide
*/
- @SystemApi
public static final int REASON_NO_REPLY = 2;
/**
@@ -110,7 +102,6 @@
* and conditions +CCFC
* @hide
*/
- @SystemApi
public static final int REASON_NOT_REACHABLE = 3;
/**
@@ -120,7 +111,6 @@
* and conditions +CCFC
* @hide
*/
- @SystemApi
public static final int REASON_ALL = 4;
/**
@@ -130,20 +120,48 @@
* and conditions +CCFC
* @hide
*/
- @SystemApi
public static final int REASON_ALL_CONDITIONAL = 5;
/**
+ * Call forwarding function status
+ */
+ @IntDef(prefix = { "STATUS_" }, value = {
+ STATUS_ACTIVE,
+ STATUS_INACTIVE,
+ STATUS_UNKNOWN_ERROR,
+ STATUS_NOT_SUPPORTED,
+ STATUS_FDN_CHECK_FAILURE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CallForwardingStatus {
+ }
+
+ /**
+ * Call forwarding reason types
+ */
+ @IntDef(flag = true, prefix = { "REASON_" }, value = {
+ REASON_UNCONDITIONAL,
+ REASON_BUSY,
+ REASON_NO_REPLY,
+ REASON_NOT_REACHABLE,
+ REASON_ALL,
+ REASON_ALL_CONDITIONAL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CallForwardingReason {
+ }
+
+ /**
* The call forwarding status.
*/
- private @CallForwardingStatus int mStatus;
+ private int mStatus;
/**
* The call forwarding reason indicates the condition under which calls will be forwarded.
* Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
* and conditions +CCFC
*/
- private @CallForwardingReason int mReason;
+ private int mReason;
/**
* The phone number to which calls will be forwarded.
@@ -166,7 +184,6 @@
* @param timeSeconds the timeout (in seconds) before the forwarding is attempted
* @hide
*/
- @SystemApi
public CallForwardingInfo(@CallForwardingStatus int status, @CallForwardingReason int reason,
@Nullable String number, int timeSeconds) {
mStatus = status;
@@ -182,7 +199,6 @@
*
* @hide
*/
- @SystemApi
public @CallForwardingStatus int getStatus() {
return mStatus;
}
@@ -196,7 +212,6 @@
*
* @hide
*/
- @SystemApi
public @CallForwardingReason int getReason() {
return mReason;
}
@@ -209,7 +224,6 @@
*
* @hide
*/
- @SystemApi
@Nullable
public String getNumber() {
return mNumber;
@@ -227,7 +241,6 @@
*
* @hide
*/
- @SystemApi
@SuppressLint("MethodNameUnits")
public int getTimeoutSeconds() {
return mTimeSeconds;
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index e37a9b9..c2cfbef 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -95,7 +95,6 @@
* if there is no valid APN setting for the specific type, then this will be null
* @hide
*/
- @SystemApi
public PreciseDataConnectionState(@DataState int state,
@NetworkType int networkType,
@ApnType int apnTypes, @NonNull String apn,
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index f6a305f..6aea5ee 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -2894,7 +2894,7 @@
getSubscriptionId(), null);
}
} catch (RemoteException ex) {
- // ignore it
+ throw new RuntimeException(ex);
}
return smsc;
}
@@ -2916,7 +2916,7 @@
* </p>
*
* @param smsc the SMSC address string.
- * @return true for success, false otherwise.
+ * @return true for success, false otherwise. Failure can be due modem returning an error.
*/
@SuppressAutoDoc // for carrier privileges and default SMS application.
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -2928,7 +2928,7 @@
smsc, getSubscriptionId(), null);
}
} catch (RemoteException ex) {
- // ignore it
+ throw new RuntimeException(ex);
}
return false;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index e559c2a..d6f5bb2 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -70,13 +70,13 @@
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.Annotation.ApnType;
-import android.telephony.Annotation.CallForwardingReason;
import android.telephony.Annotation.CallState;
-import android.telephony.Annotation.CallWaitingStatus;
+import android.telephony.Annotation.CarrierPrivilegeStatus;
import android.telephony.Annotation.NetworkType;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
import android.telephony.Annotation.UiccAppType;
+import android.telephony.CallForwardingInfo.CallForwardingReason;
import android.telephony.VisualVoicemailService.VisualVoicemailTask;
import android.telephony.data.ApnSetting;
import android.telephony.data.ApnSetting.MvnoType;
@@ -1036,7 +1036,9 @@
"android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
/**
- * Broadcast intent that indicates multi-SIM configuration is changed. For example, it changed
+ * Broadcast action to be received by Broadcast receivers.
+ *
+ * Indicates multi-SIM configuration is changed. For example, it changed
* from single SIM capable to dual-SIM capable (DSDS or DSDA) or triple-SIM mode.
*
* It doesn't indicate how many subscriptions are actually active, or which states SIMs are,
@@ -1279,7 +1281,6 @@
* <p>Note: this is a protected intent that can only be sent by the system.
* @hide
*/
- @SystemApi
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_SERVICE_PROVIDERS_UPDATED =
"android.telephony.action.SERVICE_PROVIDERS_UPDATED";
@@ -1289,7 +1290,6 @@
* whether the PLMN should be shown.
* @hide
*/
- @SystemApi
public static final String EXTRA_SHOW_PLMN = "android.telephony.extra.SHOW_PLMN";
/**
@@ -1297,7 +1297,6 @@
* the operator name of the registered network.
* @hide
*/
- @SystemApi
public static final String EXTRA_PLMN = "android.telephony.extra.PLMN";
/**
@@ -1305,7 +1304,6 @@
* whether the PLMN should be shown.
* @hide
*/
- @SystemApi
public static final String EXTRA_SHOW_SPN = "android.telephony.extra.SHOW_SPN";
/**
@@ -1313,7 +1311,6 @@
* the service provider name.
* @hide
*/
- @SystemApi
public static final String EXTRA_SPN = "android.telephony.extra.SPN";
/**
@@ -1321,7 +1318,6 @@
* the service provider name for data service.
* @hide
*/
- @SystemApi
public static final String EXTRA_DATA_SPN = "android.telephony.extra.DATA_SPN";
/**
@@ -4328,14 +4324,18 @@
/**
* Returns the phone number string for line 1, for example, the MSISDN
- * for a GSM phone. Return null if it is unavailable.
+ * for a GSM phone for a particular subscription. Return null if it is unavailable.
+ * <p>
+ * The default SMS app can also use this.
*
* <p>Requires Permission:
- * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE},
* {@link android.Manifest.permission#READ_SMS READ_SMS},
* {@link android.Manifest.permission#READ_PHONE_NUMBERS READ_PHONE_NUMBERS},
* that the caller is the default SMS app,
- * or that the caller has carrier privileges (see {@link #hasCarrierPrivileges}).
+ * or that the caller has carrier privileges (see {@link #hasCarrierPrivileges})
+ * for any API level.
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * for apps targeting SDK API level 29 and below.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges or default SMS app
@RequiresPermission(anyOf = {
@@ -4353,6 +4353,15 @@
* <p>
* The default SMS app can also use this.
*
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_SMS READ_SMS},
+ * {@link android.Manifest.permission#READ_PHONE_NUMBERS READ_PHONE_NUMBERS},
+ * that the caller is the default SMS app,
+ * or that the caller has carrier privileges (see {@link #hasCarrierPrivileges})
+ * for any API level.
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * for apps targeting SDK API level 29 and below.
+ *
* @param subId whose phone number for line 1 is returned
* @hide
*/
@@ -4533,25 +4542,50 @@
}
/**
- * Returns the MSISDN string.
- * for a GSM phone. Return null if it is unavailable.
+ * Returns the MSISDN string for a GSM phone. Return null if it is unavailable.
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_SMS READ_SMS},
+ * {@link android.Manifest.permission#READ_PHONE_NUMBERS READ_PHONE_NUMBERS},
+ * that the caller is the default SMS app,
+ * or that the caller has carrier privileges (see {@link #hasCarrierPrivileges})
+ * for any API level.
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * for apps targeting SDK API level 29 and below.
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PHONE_STATE,
+ android.Manifest.permission.READ_SMS,
+ android.Manifest.permission.READ_PHONE_NUMBERS
+ })
@UnsupportedAppUsage
public String getMsisdn() {
return getMsisdn(getSubId());
}
/**
- * Returns the MSISDN string.
- * for a GSM phone. Return null if it is unavailable.
+ * Returns the MSISDN string for a GSM phone. Return null if it is unavailable.
*
* @param subId for which msisdn is returned
+ *
+ * <p>Requires Permission:
+ * {@link android.Manifest.permission#READ_SMS READ_SMS},
+ * {@link android.Manifest.permission#READ_PHONE_NUMBERS READ_PHONE_NUMBERS},
+ * that the caller is the default SMS app,
+ * or that the caller has carrier privileges (see {@link #hasCarrierPrivileges})
+ * for any API level.
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * for apps targeting SDK API level 29 and below.
+ *
* @hide
*/
- @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.READ_PHONE_STATE,
+ android.Manifest.permission.READ_SMS,
+ android.Manifest.permission.READ_PHONE_NUMBERS
+ })
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public String getMsisdn(int subId) {
try {
@@ -9709,14 +9743,12 @@
* Powers down the SIM. SIM must be up prior.
* @hide
*/
- @SystemApi
public static final int CARD_POWER_DOWN = 0;
/**
* Powers up the SIM normally. SIM must be down prior.
* @hide
*/
- @SystemApi
public static final int CARD_POWER_UP = 1;
/**
@@ -9734,7 +9766,6 @@
* is NOT persistent across boots. On reboot, SIM will power up normally.
* @hide
*/
- @SystemApi
public static final int CARD_POWER_UP_PASS_THROUGH = 2;
/**
@@ -11163,8 +11194,6 @@
retVal = telephony.isDataEnabled(subId);
} catch (RemoteException e) {
Log.e(TAG, "Error isDataConnectionAllowed", e);
- } catch (NullPointerException e) {
- return false;
}
return retVal;
}
@@ -11179,6 +11208,8 @@
* PackageManager.FEATURE_TELEPHONY system feature, which is available
* on any device with a telephony radio, even if the device is
* voice-only.
+ *
+ * @hide
*/
public boolean isDataCapable() {
if (mContext == null) return true;
@@ -12449,7 +12480,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public int getCarrierPrivilegeStatus(int uid) {
+ public @CarrierPrivilegeStatus int getCarrierPrivilegeStatus(int uid) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
@@ -12714,7 +12745,6 @@
*
* @hide
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@NonNull
public CallForwardingInfo getCallForwarding(@CallForwardingReason int callForwardingReason) {
@@ -12761,7 +12791,6 @@
*
* @hide
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean setCallForwarding(@NonNull CallForwardingInfo callForwardingInfo) {
if (callForwardingInfo == null) {
@@ -12802,7 +12831,6 @@
*
* @hide
*/
- @SystemApi
public static final int CALL_WAITING_STATUS_ACTIVE = 1;
/**
@@ -12810,7 +12838,6 @@
*
* @hide
*/
- @SystemApi
public static final int CALL_WAITING_STATUS_INACTIVE = 2;
/**
@@ -12818,7 +12845,6 @@
*
* @hide
*/
- @SystemApi
public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3;
/**
@@ -12826,10 +12852,24 @@
*
* @hide
*/
- @SystemApi
public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4;
/**
+ * Call waiting function status
+ *
+ * @hide
+ */
+ @IntDef(prefix = { "CALL_WAITING_STATUS_" }, value = {
+ CALL_WAITING_STATUS_ACTIVE,
+ CALL_WAITING_STATUS_INACTIVE,
+ CALL_WAITING_STATUS_NOT_SUPPORTED,
+ CALL_WAITING_STATUS_UNKNOWN_ERROR
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CallWaitingStatus {
+ }
+
+ /**
* Gets the status of voice call waiting function. Call waiting function enables the waiting
* for the incoming call when it reaches the user who is busy to make another call and allows
* users to decide whether to switch to the incoming call.
@@ -12837,7 +12877,6 @@
* @return the status of call waiting function.
* @hide
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @CallWaitingStatus int getCallWaitingStatus() {
try {
@@ -12863,7 +12902,6 @@
*
* @hide
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public boolean setCallWaitingStatus(boolean isEnable) {
try {
diff --git a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java b/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
index ae20cae..629b6c7 100644
--- a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
+++ b/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
@@ -98,7 +98,8 @@
mDevice = getDevice();
String apkVerityMode = mDevice.getProperty("ro.apk_verity.mode");
- assumeTrue(APK_VERITY_STANDARD_MODE.equals(apkVerityMode));
+ assumeTrue(mDevice.getLaunchApiLevel() >= 30
+ || APK_VERITY_STANDARD_MODE.equals(apkVerityMode));
mKeyId = expectRemoteCommandToSucceed(
"mini-keyctl padd asymmetric fsv_test .fs-verity < " + CERT_PATH).trim();
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index da45d9a..2f9a1c8 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -71,6 +71,7 @@
// with the app launch
private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts";
private static final String KEY_APPS = "apps";
+ private static final String KEY_IORAP_TRIAL_LAUNCH = "iorap_trial_launch";
private static final String KEY_TRIAL_LAUNCH = "trial_launch";
private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations";
private static final String KEY_LAUNCH_ORDER = "launch_order";
@@ -98,6 +99,9 @@
private static final int BEFORE_KILL_APP_SLEEP_TIMEOUT = 1000; // 1s before killing
private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 3000; // 3s between launching apps
private static final int PROFILE_SAVE_SLEEP_TIMEOUT = 1000; // Allow 1s for the profile to save
+ private static final int IORAP_TRACE_DURATION_TIMEOUT = 7000; // Allow 7s for trace to complete.
+ private static final int IORAP_TRIAL_LAUNCH_ITERATIONS = 3; // min 3 launches to merge traces.
+ private static final int IORAP_COMPILE_CMD_TIMEOUT = 600; // in seconds: 10 minutes
private static final String LAUNCH_SUB_DIRECTORY = "launch_logs";
private static final String LAUNCH_FILE = "applaunch.txt";
private static final String TRACE_SUB_DIRECTORY = "atrace_logs";
@@ -106,6 +110,9 @@
private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000";
private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10";
private static final String TRIAL_LAUNCH = "TRIAL_LAUNCH";
+ private static final String IORAP_TRIAL_LAUNCH = "IORAP_TRIAL_LAUNCH";
+ private static final String IORAP_TRIAL_LAUNCH_FIRST = "IORAP_TRIAL_LAUNCH_FIRST";
+ private static final String IORAP_TRIAL_LAUNCH_LAST = "IORAP_TRIAL_LAUNCH_LAST";
private static final String DELIMITER = ",";
private static final String DROP_CACHE_SCRIPT = "/data/local/tmp/dropCache.sh";
private static final String APP_LAUNCH_CMD = "am start -W -n";
@@ -119,6 +126,10 @@
private static final String LAUNCH_ORDER_CYCLIC = "cyclic";
private static final String LAUNCH_ORDER_SEQUENTIAL = "sequential";
private static final String COMPILE_CMD = "cmd package compile -f -m %s %s";
+ private static final String IORAP_COMPILE_CMD = "cmd jobscheduler run -f android 283673059";
+ private static final String IORAP_MAINTENANCE_CMD =
+ "iorap.cmd.maintenance --purge-package %s /data/misc/iorapd/sqlite.db";
+ private static final String IORAP_DUMPSYS_CMD = "dumpsys iorapd";
private static final String SPEED_PROFILE_FILTER = "speed-profile";
private static final String VERIFY_FILTER = "verify";
private static final String LAUNCH_SCRIPT_NAME = "appLaunch";
@@ -138,6 +149,7 @@
private Bundle mResult = new Bundle();
private Set<String> mRequiredAccounts;
private boolean mTrialLaunch = false;
+ private boolean mIorapTrialLaunch = false;
private BufferedWriter mBufferedWriter = null;
private boolean mSimplePerfAppOnly = false;
private String[] mCompilerFilters = null;
@@ -145,6 +157,13 @@
private boolean mCycleCleanUp = false;
private boolean mTraceAll = false;
private boolean mIterationCycle = false;
+
+ enum IorapStatus {
+ UNDEFINED,
+ ENABLED,
+ DISABLED
+ }
+ private IorapStatus mIorapStatus = IorapStatus.UNDEFINED;
private long mCycleTime = 0;
private StringBuilder mCycleTimes = new StringBuilder();
@@ -243,7 +262,10 @@
setLaunchOrder();
for (LaunchOrder launch : mLaunchOrderList) {
- dropCache();
+ toggleIorapStatus(launch.getIorapEnabled());
+ dropCache(/*override*/false);
+
+ Log.v(TAG, "Launch reason: " + launch.getLaunchReason());
// App launch times for trial launch will not be used for final
// launch time calculations.
@@ -289,6 +311,43 @@
compileApp(launch.getCompilerFilter(), appPkgName));
}
}
+ else if (launch.getLaunchReason().startsWith(IORAP_TRIAL_LAUNCH)) {
+ mIterationCycle = false;
+
+ // In the "applaunch.txt" file, iorap-trial launches is referenced using
+ // "IORAP_TRIAL_LAUNCH" or "IORAP_TRIAL_LAUNCH_LAST"
+ Intent startIntent = mNameToIntent.get(launch.getApp());
+ if (startIntent == null) {
+ Log.w(TAG, "App does not exist: " + launch.getApp());
+ mResult.putString(mNameToResultKey.get(launch.getApp()),
+ "App does not exist");
+ continue;
+ }
+ String appPkgName = startIntent.getComponent().getPackageName();
+
+ if (launch.getLaunchReason().equals(IORAP_TRIAL_LAUNCH_FIRST)) {
+ // delete any iorap-traces associated with this package.
+ purgeIorapPackage(appPkgName);
+ }
+ dropCache(/*override*/true); // iorap-trial runs must have drop cache.
+
+ AppLaunchResult launchResult =
+ startApp(launch.getApp(), launch.getLaunchReason());
+ if (launchResult.mLaunchTime < 0) {
+ addLaunchResult(launch, new AppLaunchResult());
+ // simply pass the app if launch isn't successful
+ // error should have already been logged by startApp
+ continue;
+ }
+ // wait for slightly more than 5s (iorapd.perfetto.trace_duration_ms) for the trace buffers to complete.
+ sleep(IORAP_TRACE_DURATION_TIMEOUT);
+
+ if (launch.getLaunchReason().equals(IORAP_TRIAL_LAUNCH_LAST)) {
+ // run the iorap job scheduler and wait for iorap to compile fully.
+ assertTrue(String.format("Not able to iorap-compile the app : %s", appPkgName),
+ compileAppForIorap(appPkgName));
+ }
+ }
// App launch times used for final calculation
else if (launch.getLaunchReason().contains(LAUNCH_ITERATION_PREFIX)) {
@@ -440,6 +499,74 @@
}
/**
+ * Compile the app package using compilerFilter and return true or false
+ * based on status of the compilation command.
+ */
+ private boolean compileAppForIorap(String appPkgName) throws IOException {
+ getInstrumentation().getUiAutomation().
+ executeShellCommand(IORAP_COMPILE_CMD);
+
+ for (int i = 0; i < IORAP_COMPILE_CMD_TIMEOUT; ++i) {
+ IorapCompilationStatus status = waitForIorapCompiled(appPkgName);
+ if (status == IorapCompilationStatus.COMPLETE) {
+ return true;
+ } else if (status == IorapCompilationStatus.INSUFFICIENT_TRACES) {
+ return false;
+ } // else INCOMPLETE. keep asking iorapd if it's done yet.
+ sleep(1000);
+ }
+
+ return false;
+ }
+
+ enum IorapCompilationStatus {
+ INCOMPLETE,
+ COMPLETE,
+ INSUFFICIENT_TRACES,
+ }
+ private IorapCompilationStatus waitForIorapCompiled(String appPkgName) throws IOException {
+ try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation().
+ executeShellCommand(IORAP_DUMPSYS_CMD);
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
+ new FileInputStream(result.getFileDescriptor())))) {
+ String line;
+ String prevLine = "";
+ while ((line = bufferedReader.readLine()) != null) {
+ // Match the indented VersionedComponentName string.
+ // " com.google.android.deskclock/com.android.deskclock.DeskClock@62000712"
+ // Note: spaces are meaningful here.
+ if (prevLine.contains(" " + appPkgName) && prevLine.contains("@")) {
+ // pre-requisite:
+ // Compiled Status: Raw traces pending compilation (3)
+ if (line.contains("Compiled Status: Usable compiled trace")) {
+ return IorapCompilationStatus.COMPLETE;
+ } else if (line.contains("Compiled Status: ") &&
+ line.contains("more traces for compilation")) {
+ // Compiled Status: Need 1 more traces for compilation
+ // No amount of waiting will help here because there were
+ // insufficient traces made.
+ return IorapCompilationStatus.INSUFFICIENT_TRACES;
+ }
+ }
+
+ prevLine = line;
+ }
+ return IorapCompilationStatus.INCOMPLETE;
+ }
+ }
+
+ private String makeReasonForIorapTrialLaunch(int launchCount) {
+ String reason = IORAP_TRIAL_LAUNCH;
+ if (launchCount == 0) {
+ reason = IORAP_TRIAL_LAUNCH_FIRST;
+ }
+ if (launchCount == IORAP_TRIAL_LAUNCH_ITERATIONS - 1) {
+ reason = IORAP_TRIAL_LAUNCH_LAST;
+ }
+ return reason;
+ }
+
+ /**
* If launch order is "cyclic" then apps will be launched one after the
* other for each iteration count.
* If launch order is "sequential" then each app will be launched for given number
@@ -450,20 +577,31 @@
for (String compilerFilter : mCompilerFilters) {
if (mTrialLaunch) {
for (String app : mNameToResultKey.keySet()) {
- mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH));
+ mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH, /*iorapEnabled*/false));
+ }
+ }
+ if (mIorapTrialLaunch) {
+ for (int launchCount = 0; launchCount < IORAP_TRIAL_LAUNCH_ITERATIONS; ++launchCount) {
+ for (String app : mNameToResultKey.keySet()) {
+ String reason = makeReasonForIorapTrialLaunch(launchCount);
+ mLaunchOrderList.add(
+ new LaunchOrder(app, compilerFilter,
+ reason,
+ /*iorapEnabled*/true));
+ }
}
}
for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
for (String app : mNameToResultKey.keySet()) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
- String.format(LAUNCH_ITERATION, launchCount)));
+ String.format(LAUNCH_ITERATION, launchCount), mIorapTrialLaunch));
}
}
if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
for (String app : mNameToResultKey.keySet()) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
- String.format(TRACE_ITERATION, traceCount)));
+ String.format(TRACE_ITERATION, traceCount), mIorapTrialLaunch));
}
}
}
@@ -472,16 +610,25 @@
for (String compilerFilter : mCompilerFilters) {
for (String app : mNameToResultKey.keySet()) {
if (mTrialLaunch) {
- mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH));
+ mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH, /*iorapEnabled*/false));
+ }
+ if (mIorapTrialLaunch) {
+ for (int launchCount = 0; launchCount < IORAP_TRIAL_LAUNCH_ITERATIONS; ++launchCount) {
+ String reason = makeReasonForIorapTrialLaunch(launchCount);
+ mLaunchOrderList.add(
+ new LaunchOrder(app, compilerFilter,
+ reason,
+ /*iorapEnabled*/true));
+ }
}
for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
- String.format(LAUNCH_ITERATION, launchCount)));
+ String.format(LAUNCH_ITERATION, launchCount), mIorapTrialLaunch));
}
if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
- String.format(TRACE_ITERATION, traceCount)));
+ String.format(TRACE_ITERATION, traceCount), mIorapTrialLaunch));
}
}
}
@@ -491,14 +638,92 @@
}
}
- private void dropCache() {
- if (mDropCache) {
+ private void dropCache(boolean override) {
+ if (mDropCache || override) {
assertNotNull("Issue in dropping the cache",
getInstrumentation().getUiAutomation()
.executeShellCommand(DROP_CACHE_SCRIPT));
}
}
+ // [[ $(adb shell whoami) == "root" ]]
+ private boolean checkIfRoot() throws IOException {
+ String total = "";
+ try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation().
+ executeShellCommand("whoami");
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
+ new FileInputStream(result.getFileDescriptor())))) {
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ total = total + line;
+ }
+ }
+ return total.contains("root");
+ }
+
+ // Delete all db rows and files associated with a package in iorapd.
+ // Effectively deletes any raw or compiled trace files, unoptimizing the package in iorap.
+ private void purgeIorapPackage(String packageName) {
+ try {
+ if (!checkIfRoot()) {
+ throw new AssertionError("must be root to toggle iorapd; try adb root?");
+ }
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand("stop iorapd");
+ sleep(100); // give iorapd enough time to stop.
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand(String.format(IORAP_MAINTENANCE_CMD, packageName));
+ Log.v(TAG, "Executed: " + String.format(IORAP_MAINTENANCE_CMD, packageName));
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand("start iorapd");
+ sleep(2000); // give iorapd enough time to start up.
+ }
+
+ /**
+ * Toggle iorapd-based readahead and trace-collection.
+ * If iorapd is already enabled and enable is true, does nothing.
+ * If iorapd is already disabled and enable is false, does nothing.
+ */
+ private void toggleIorapStatus(boolean enable) {
+ boolean currentlyEnabled = false;
+ Log.v(TAG, "toggleIorapStatus " + Boolean.toString(enable));
+
+ // Do nothing if we are already enabled or disabled.
+ if (mIorapStatus == IorapStatus.ENABLED && enable) {
+ return;
+ } else if (mIorapStatus == IorapStatus.DISABLED && !enable) {
+ return;
+ }
+
+ try {
+ if (!checkIfRoot()) {
+ throw new AssertionError("must be root to toggle iorapd; try adb root?");
+ }
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand("stop iorapd");
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand(String.format("setprop iorapd.perfetto.enable %b", enable));
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand(String.format("setprop iorapd.readahead.enable %b", enable));
+ getInstrumentation().getUiAutomation()
+ .executeShellCommand("start iorapd");
+ sleep(2000); // give enough time for iorapd to start back up.
+
+ if (enable) {
+ mIorapStatus = IorapStatus.ENABLED;
+ } else {
+ mIorapStatus = IorapStatus.DISABLED;
+ }
+ }
+
private void parseArgs(Bundle args) {
mNameToResultKey = new LinkedHashMap<String, String>();
mNameToLaunchTime = new HashMap<>();
@@ -562,6 +787,8 @@
mCycleCleanUp = Boolean.parseBoolean(args.getString(KEY_CYCLE_CLEAN));
mTraceAll = Boolean.parseBoolean(args.getString(KEY_TRACE_ALL));
mTrialLaunch = mTrialLaunch || Boolean.parseBoolean(args.getString(KEY_TRIAL_LAUNCH));
+ mIorapTrialLaunch = mIorapTrialLaunch ||
+ Boolean.parseBoolean(args.getString(KEY_IORAP_TRIAL_LAUNCH));
if (mSimplePerfCmd != null && mSimplePerfAppOnly) {
Log.w(TAG, String.format("Passing both %s and %s is not supported, ignoring %s",
@@ -740,11 +967,13 @@
private String mApp;
private String mCompilerFilter;
private String mLaunchReason;
+ private boolean mIorapEnabled;
- LaunchOrder(String app, String compilerFilter, String launchReason){
+ LaunchOrder(String app, String compilerFilter, String launchReason, boolean iorapEnabled) {
mApp = app;
mCompilerFilter = compilerFilter;
mLaunchReason = launchReason;
+ mIorapEnabled = iorapEnabled;
}
public String getApp() {
@@ -766,6 +995,14 @@
public void setLaunchReason(String launchReason) {
mLaunchReason = launchReason;
}
+
+ public void setIorapEnabled(boolean iorapEnabled) {
+ mIorapEnabled = iorapEnabled;
+ }
+
+ public boolean getIorapEnabled() {
+ return mIorapEnabled;
+ }
}
private class AppLaunchResult {
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index dfaac2c..2957192 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -1077,6 +1077,52 @@
assertThat(observer1.mMitigatedPackages).isEmpty();
}
+ /**
+ * Test to verify that Package Watchdog syncs health check requests with the controller
+ * correctly, and that the requests are only synced when the set of observed packages
+ * changes.
+ */
+ @Test
+ public void testSyncHealthCheckRequests() {
+ TestController testController = spy(TestController.class);
+ testController.setSupportedPackages(List.of(APP_A, APP_B, APP_C));
+ PackageWatchdog watchdog = createWatchdog(testController, true);
+
+ TestObserver testObserver1 = new TestObserver(OBSERVER_NAME_1);
+ watchdog.registerHealthObserver(testObserver1);
+ watchdog.startObservingHealth(testObserver1, List.of(APP_A), LONG_DURATION);
+ mTestLooper.dispatchAll();
+
+ TestObserver testObserver2 = new TestObserver(OBSERVER_NAME_2);
+ watchdog.registerHealthObserver(testObserver2);
+ watchdog.startObservingHealth(testObserver2, List.of(APP_B), LONG_DURATION);
+ mTestLooper.dispatchAll();
+
+ TestObserver testObserver3 = new TestObserver(OBSERVER_NAME_3);
+ watchdog.registerHealthObserver(testObserver3);
+ watchdog.startObservingHealth(testObserver3, List.of(APP_C), LONG_DURATION);
+ mTestLooper.dispatchAll();
+
+ watchdog.unregisterHealthObserver(testObserver1);
+ mTestLooper.dispatchAll();
+
+ watchdog.unregisterHealthObserver(testObserver2);
+ mTestLooper.dispatchAll();
+
+ watchdog.unregisterHealthObserver(testObserver3);
+ mTestLooper.dispatchAll();
+
+ List<Set> expectedSyncRequests = List.of(
+ Set.of(APP_A),
+ Set.of(APP_A, APP_B),
+ Set.of(APP_A, APP_B, APP_C),
+ Set.of(APP_B, APP_C),
+ Set.of(APP_C),
+ Set.of()
+ );
+ assertThat(testController.getSyncRequests()).isEqualTo(expectedSyncRequests);
+ }
+
private void adoptShellPermissions(String... permissions) {
InstrumentationRegistry
.getInstrumentation()
@@ -1233,6 +1279,7 @@
private Consumer<String> mPassedConsumer;
private Consumer<List<PackageConfig>> mSupportedConsumer;
private Runnable mNotifySyncRunnable;
+ private List<Set> mSyncRequests = new ArrayList<>();
@Override
public void setEnabled(boolean enabled) {
@@ -1252,6 +1299,7 @@
@Override
public void syncRequests(Set<String> packages) {
+ mSyncRequests.add(packages);
mRequestedPackages.clear();
if (mIsEnabled) {
packages.retainAll(mSupportedPackages);
@@ -1282,6 +1330,10 @@
return Collections.emptyList();
}
}
+
+ public List<Set> getSyncRequests() {
+ return mSyncRequests;
+ }
}
private static class TestClock implements PackageWatchdog.SystemClock {
diff --git a/tests/RollbackTest/RollbackTest.xml b/tests/RollbackTest/RollbackTest.xml
index f2c0f86..269cec1 100644
--- a/tests/RollbackTest/RollbackTest.xml
+++ b/tests/RollbackTest/RollbackTest.xml
@@ -18,6 +18,12 @@
<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
<option name="test-file-name" value="RollbackTest.apk" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="am broadcast -a 'com.google.android.gms.phenotype.FLAG_OVERRIDE' --es package "com.google.android.gms.platformconfigurator" --es user '\\*' --esa flags "ModuleConfig__immediate_commit_packages" --esa types "bytes" --esa values "CgA=" com.google.android.gms" />
+ <option name="run-command" value="am broadcast -a 'com.google.android.gms.phenotype.FLAG_OVERRIDE' --es package "com.google.android.gms.platformconfigurator" --es user '\\*' --esa flags "ModuleConfig__versioned_immediate_commit_packages" --esa types "bytes" --esa values "Cm5vdGFwYWNrYWdlOgA=" com.google.android.gms" />
+ <option name="teardown-command" value="am broadcast -a 'com.google.android.gms.phenotype.FLAG_OVERRIDE' --es action delete --es package "com.google.android.gms.platformconfigurator" --es user '\*' --esa flag "ModuleConfig__immediate_commit_packages" com.google.android.gms" />
+ <option name="teardown-command" value="am broadcast -a 'com.google.android.gms.phenotype.FLAG_OVERRIDE' --es action delete --es package "com.google.android.gms.platformconfigurator" --es user '\*' --esa flag "ModuleConfig__versioned_immediate_commit_packages" com.google.android.gms" />
+ </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.tests.rollback" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
diff --git a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java
index f254e4d..548af0c 100644
--- a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java
+++ b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java
@@ -114,7 +114,14 @@
}
@Override
- public void onCancelled() {
+ public void onFinished(
+ WindowInsetsAnimationController controller) {
+ mAnimationController = null;
+ }
+
+ @Override
+ public void onCancelled(
+ WindowInsetsAnimationController controller) {
mAnimationController = null;
}
});
@@ -230,7 +237,13 @@
}
@Override
- public void onCancelled() {
+ public void onFinished(
+ WindowInsetsAnimationController controller) {
+ }
+
+ @Override
+ public void onCancelled(
+ WindowInsetsAnimationController controller) {
}
});
}
diff --git a/tests/net/AndroidManifest.xml b/tests/net/AndroidManifest.xml
index 480b12b..009f817 100644
--- a/tests/net/AndroidManifest.xml
+++ b/tests/net/AndroidManifest.xml
@@ -47,6 +47,7 @@
<uses-permission android:name="android.permission.NETWORK_STACK" />
<uses-permission android:name="android.permission.OBSERVE_NETWORK_POLICY" />
<uses-permission android:name="android.permission.NETWORK_FACTORY" />
+ <uses-permission android:name="android.permission.NETWORK_STATS_PROVIDER" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/tests/net/common/Android.bp b/tests/net/common/Android.bp
index e44d460..46d680f 100644
--- a/tests/net/common/Android.bp
+++ b/tests/net/common/Android.bp
@@ -20,6 +20,7 @@
name: "FrameworksNetCommonTests",
srcs: ["java/**/*.java", "java/**/*.kt"],
static_libs: [
+ "androidx.core_core",
"androidx.test.rules",
"junit",
"mockito-target-minus-junit4",
diff --git a/tests/net/common/java/android/net/KeepalivePacketDataTest.kt b/tests/net/common/java/android/net/KeepalivePacketDataTest.kt
new file mode 100644
index 0000000..f464ec6
--- /dev/null
+++ b/tests/net/common/java/android/net/KeepalivePacketDataTest.kt
@@ -0,0 +1,120 @@
+/*
+ * 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.net
+
+import android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS
+import android.net.InvalidPacketException.ERROR_INVALID_PORT
+import android.os.Build
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
+import java.net.InetAddress
+import java.util.Arrays
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Assert.fail
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class KeepalivePacketDataTest {
+ @Rule @JvmField
+ val ignoreRule: DevSdkIgnoreRule = DevSdkIgnoreRule()
+
+ private val INVALID_PORT = 65537
+ private val TEST_DST_PORT = 4244
+ private val TEST_SRC_PORT = 4243
+
+ private val TESTBYTES = byteArrayOf(12, 31, 22, 44)
+ private val TEST_SRC_ADDRV4 = "198.168.0.2".address()
+ private val TEST_DST_ADDRV4 = "198.168.0.1".address()
+ private val TEST_ADDRV6 = "2001:db8::1".address()
+
+ private fun String.address() = InetAddresses.parseNumericAddress(this)
+
+ // Add for test because constructor of KeepalivePacketData is protected.
+ private inner class TestKeepalivePacketData(
+ srcAddress: InetAddress? = TEST_SRC_ADDRV4,
+ srcPort: Int = TEST_SRC_PORT,
+ dstAddress: InetAddress? = TEST_DST_ADDRV4,
+ dstPort: Int = TEST_DST_PORT,
+ data: ByteArray = TESTBYTES
+ ) : KeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, data)
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testConstructor() {
+ var data: TestKeepalivePacketData
+
+ try {
+ data = TestKeepalivePacketData(srcAddress = null)
+ fail("Null src address should cause exception")
+ } catch (e: InvalidPacketException) {
+ assertEquals(e.error, ERROR_INVALID_IP_ADDRESS)
+ }
+
+ try {
+ data = TestKeepalivePacketData(dstAddress = null)
+ fail("Null dst address should cause exception")
+ } catch (e: InvalidPacketException) {
+ assertEquals(e.error, ERROR_INVALID_IP_ADDRESS)
+ }
+
+ try {
+ data = TestKeepalivePacketData(dstAddress = TEST_ADDRV6)
+ fail("Ip family mismatched should cause exception")
+ } catch (e: InvalidPacketException) {
+ assertEquals(e.error, ERROR_INVALID_IP_ADDRESS)
+ }
+
+ try {
+ data = TestKeepalivePacketData(srcPort = INVALID_PORT)
+ fail("Invalid srcPort should cause exception")
+ } catch (e: InvalidPacketException) {
+ assertEquals(e.error, ERROR_INVALID_PORT)
+ }
+
+ try {
+ data = TestKeepalivePacketData(dstPort = INVALID_PORT)
+ fail("Invalid dstPort should cause exception")
+ } catch (e: InvalidPacketException) {
+ assertEquals(e.error, ERROR_INVALID_PORT)
+ }
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testSrcAddress() = assertEquals(TEST_SRC_ADDRV4, TestKeepalivePacketData().srcAddress)
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testDstAddress() = assertEquals(TEST_DST_ADDRV4, TestKeepalivePacketData().dstAddress)
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testSrcPort() = assertEquals(TEST_SRC_PORT, TestKeepalivePacketData().srcPort)
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testDstPort() = assertEquals(TEST_DST_PORT, TestKeepalivePacketData().dstPort)
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testPacket() = assertTrue(Arrays.equals(TESTBYTES, TestKeepalivePacketData().packet))
+}
\ No newline at end of file
diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java
index 48b65e5..2b5720a 100644
--- a/tests/net/common/java/android/net/LinkPropertiesTest.java
+++ b/tests/net/common/java/android/net/LinkPropertiesTest.java
@@ -29,12 +29,19 @@
import android.net.LinkProperties.ProvisioningChange;
import android.net.util.LinkPropertiesUtils.CompareResult;
+import android.os.Build;
import android.system.OsConstants;
import android.util.ArraySet;
+import androidx.core.os.BuildCompat;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -50,6 +57,9 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class LinkPropertiesTest {
+ @Rule
+ public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
+
private static final InetAddress ADDRV4 = address("75.208.6.1");
private static final InetAddress ADDRV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:7334");
private static final InetAddress DNS1 = address("75.208.7.1");
@@ -76,13 +86,23 @@
private static final LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
private static final LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");
private static final Uri CAPPORT_API_URL = Uri.parse("https://test.example.com/capportapi");
- private static final CaptivePortalData CAPPORT_DATA = new CaptivePortalData.Builder()
- .setVenueInfoUrl(Uri.parse("https://test.example.com/venue")).build();
+
+ // CaptivePortalData cannot be in a constant as it does not exist on Q.
+ // The test runner also crashes when scanning for tests if it is a return type.
+ private static Object getCaptivePortalData() {
+ return new CaptivePortalData.Builder()
+ .setVenueInfoUrl(Uri.parse("https://test.example.com/venue")).build();
+ }
private static InetAddress address(String addrString) {
return InetAddresses.parseNumericAddress(addrString);
}
+ private static boolean isAtLeastR() {
+ // BuildCompat.isAtLeastR is documented to return false on release SDKs (including R)
+ return Build.VERSION.SDK_INT > Build.VERSION_CODES.Q || BuildCompat.isAtLeastR();
+ }
+
private void checkEmpty(final LinkProperties lp) {
assertEquals(0, lp.getAllInterfaceNames().size());
assertEquals(0, lp.getAllAddresses().size());
@@ -98,14 +118,17 @@
assertNull(lp.getHttpProxy());
assertNull(lp.getTcpBufferSizes());
assertNull(lp.getNat64Prefix());
- assertNull(lp.getDhcpServerAddress());
assertFalse(lp.isProvisioned());
assertFalse(lp.isIpv4Provisioned());
assertFalse(lp.isIpv6Provisioned());
assertFalse(lp.isPrivateDnsActive());
- assertFalse(lp.isWakeOnLanSupported());
- assertNull(lp.getCaptivePortalApiUrl());
- assertNull(lp.getCaptivePortalData());
+
+ if (isAtLeastR()) {
+ assertNull(lp.getDhcpServerAddress());
+ assertFalse(lp.isWakeOnLanSupported());
+ assertNull(lp.getCaptivePortalApiUrl());
+ assertNull(lp.getCaptivePortalData());
+ }
}
private LinkProperties makeTestObject() {
@@ -127,10 +150,12 @@
lp.setMtu(MTU);
lp.setTcpBufferSizes(TCP_BUFFER_SIZES);
lp.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96"));
- lp.setDhcpServerAddress(DHCPSERVER);
- lp.setWakeOnLanSupported(true);
- lp.setCaptivePortalApiUrl(CAPPORT_API_URL);
- lp.setCaptivePortalData(CAPPORT_DATA);
+ if (isAtLeastR()) {
+ lp.setDhcpServerAddress(DHCPSERVER);
+ lp.setWakeOnLanSupported(true);
+ lp.setCaptivePortalApiUrl(CAPPORT_API_URL);
+ lp.setCaptivePortalData((CaptivePortalData) getCaptivePortalData());
+ }
return lp;
}
@@ -169,14 +194,19 @@
assertTrue(source.isIdenticalTcpBufferSizes(target));
assertTrue(target.isIdenticalTcpBufferSizes(source));
- assertTrue(source.isIdenticalWakeOnLan(target));
- assertTrue(target.isIdenticalWakeOnLan(source));
+ if (isAtLeastR()) {
+ assertTrue(source.isIdenticalDhcpServerAddress(target));
+ assertTrue(source.isIdenticalDhcpServerAddress(source));
- assertTrue(source.isIdenticalCaptivePortalApiUrl(target));
- assertTrue(target.isIdenticalCaptivePortalApiUrl(source));
+ assertTrue(source.isIdenticalWakeOnLan(target));
+ assertTrue(target.isIdenticalWakeOnLan(source));
- assertTrue(source.isIdenticalCaptivePortalData(target));
- assertTrue(target.isIdenticalCaptivePortalData(source));
+ assertTrue(source.isIdenticalCaptivePortalApiUrl(target));
+ assertTrue(target.isIdenticalCaptivePortalApiUrl(source));
+
+ assertTrue(source.isIdenticalCaptivePortalData(target));
+ assertTrue(target.isIdenticalCaptivePortalData(source));
+ }
// Check result of equals().
assertTrue(source.equals(target));
@@ -943,8 +973,7 @@
assertEquals(new ArraySet<>(expectRemoved), (new ArraySet<>(result.removed)));
}
- @Test
- public void testLinkPropertiesParcelable() throws Exception {
+ private static LinkProperties makeLinkPropertiesForParceling() {
LinkProperties source = new LinkProperties();
source.setInterfaceName(NAME);
@@ -978,17 +1007,29 @@
source.setNat64Prefix(new IpPrefix("2001:db8:1:2:64:64::/96"));
- source.setWakeOnLanSupported(true);
- source.setCaptivePortalApiUrl(CAPPORT_API_URL);
- source.setCaptivePortalData(CAPPORT_DATA);
-
- source.setDhcpServerAddress((Inet4Address) GATEWAY1);
-
final LinkProperties stacked = new LinkProperties();
stacked.setInterfaceName("test-stacked");
source.addStackedLink(stacked);
- assertParcelSane(source.makeSensitiveFieldsParcelingCopy(), 18 /* fieldCount */);
+ return source;
+ }
+
+ @Test @IgnoreAfter(Build.VERSION_CODES.Q)
+ public void testLinkPropertiesParcelable_Q() throws Exception {
+ final LinkProperties source = makeLinkPropertiesForParceling();
+ assertParcelSane(source, 14 /* fieldCount */);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ public void testLinkPropertiesParcelable() throws Exception {
+ final LinkProperties source = makeLinkPropertiesForParceling();
+
+ source.setWakeOnLanSupported(true);
+ source.setCaptivePortalApiUrl(CAPPORT_API_URL);
+ source.setCaptivePortalData((CaptivePortalData) getCaptivePortalData());
+ source.setDhcpServerAddress((Inet4Address) GATEWAY1);
+ assertParcelSane(new LinkProperties(source, true /* parcelSensitiveFields */),
+ 18 /* fieldCount */);
// Verify that without using a sensitiveFieldsParcelingCopy, sensitive fields are cleared.
final LinkProperties sanitized = new LinkProperties(source);
@@ -997,7 +1038,8 @@
assertEquals(sanitized, parcelingRoundTrip(source));
}
- @Test
+ // Parceling of the scope was broken until Q-QPR2
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
public void testLinkLocalDnsServerParceling() throws Exception {
final String strAddress = "fe80::1%lo";
final LinkProperties lp = new LinkProperties();
@@ -1120,7 +1162,7 @@
assertFalse(lp.isPrivateDnsActive());
}
- @Test
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
public void testDhcpServerAddress() {
final LinkProperties lp = makeTestObject();
assertEquals(DHCPSERVER, lp.getDhcpServerAddress());
@@ -1129,7 +1171,7 @@
assertNull(lp.getDhcpServerAddress());
}
- @Test
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
public void testWakeOnLanSupported() {
final LinkProperties lp = makeTestObject();
assertTrue(lp.isWakeOnLanSupported());
@@ -1138,7 +1180,7 @@
assertFalse(lp.isWakeOnLanSupported());
}
- @Test
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
public void testCaptivePortalApiUrl() {
final LinkProperties lp = makeTestObject();
assertEquals(CAPPORT_API_URL, lp.getCaptivePortalApiUrl());
@@ -1147,10 +1189,10 @@
assertNull(lp.getCaptivePortalApiUrl());
}
- @Test
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
public void testCaptivePortalData() {
final LinkProperties lp = makeTestObject();
- assertEquals(CAPPORT_DATA, lp.getCaptivePortalData());
+ assertEquals(getCaptivePortalData(), lp.getCaptivePortalData());
lp.clear();
assertNull(lp.getCaptivePortalData());
diff --git a/tests/net/common/java/android/net/NattKeepalivePacketDataTest.kt b/tests/net/common/java/android/net/NattKeepalivePacketDataTest.kt
new file mode 100644
index 0000000..46f39dd
--- /dev/null
+++ b/tests/net/common/java/android/net/NattKeepalivePacketDataTest.kt
@@ -0,0 +1,114 @@
+/*
+ * 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.net
+
+import android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS
+import android.net.InvalidPacketException.ERROR_INVALID_PORT
+import android.net.NattSocketKeepalive.NATT_PORT
+import android.os.Build
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.testutils.assertEqualBothWays
+import com.android.testutils.assertFieldCountEquals
+import com.android.testutils.assertParcelSane
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
+import com.android.testutils.parcelingRoundTrip
+import java.net.InetAddress
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotEquals
+import org.junit.Assert.fail
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class NattKeepalivePacketDataTest {
+ @Rule @JvmField
+ val ignoreRule: DevSdkIgnoreRule = DevSdkIgnoreRule()
+
+ /* Refer to the definition in {@code NattKeepalivePacketData} */
+ private val IPV4_HEADER_LENGTH = 20
+ private val UDP_HEADER_LENGTH = 8
+
+ private val TEST_PORT = 4243
+ private val TEST_PORT2 = 4244
+ private val TEST_SRC_ADDRV4 = "198.168.0.2".address()
+ private val TEST_DST_ADDRV4 = "198.168.0.1".address()
+ private val TEST_ADDRV6 = "2001:db8::1".address()
+
+ private fun String.address() = InetAddresses.parseNumericAddress(this)
+ private fun nattKeepalivePacket(
+ srcAddress: InetAddress? = TEST_SRC_ADDRV4,
+ srcPort: Int = TEST_PORT,
+ dstAddress: InetAddress? = TEST_DST_ADDRV4,
+ dstPort: Int = NATT_PORT
+ ) = NattKeepalivePacketData.nattKeepalivePacket(srcAddress, srcPort, dstAddress, dstPort)
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testConstructor() {
+ try {
+ nattKeepalivePacket(dstPort = TEST_PORT)
+ fail("Dst port is not NATT port should cause exception")
+ } catch (e: InvalidPacketException) {
+ assertEquals(e.error, ERROR_INVALID_PORT)
+ }
+
+ try {
+ nattKeepalivePacket(srcAddress = TEST_ADDRV6)
+ fail("A v6 srcAddress should cause exception")
+ } catch (e: InvalidPacketException) {
+ assertEquals(e.error, ERROR_INVALID_IP_ADDRESS)
+ }
+
+ try {
+ nattKeepalivePacket(dstAddress = TEST_ADDRV6)
+ fail("A v6 dstAddress should cause exception")
+ } catch (e: InvalidPacketException) {
+ assertEquals(e.error, ERROR_INVALID_IP_ADDRESS)
+ }
+
+ try {
+ parcelingRoundTrip(
+ NattKeepalivePacketData(TEST_SRC_ADDRV4, TEST_PORT, TEST_DST_ADDRV4, TEST_PORT,
+ byteArrayOf(12, 31, 22, 44)))
+ fail("Invalid data should cause exception")
+ } catch (e: IllegalArgumentException) { }
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testParcel() {
+ assertParcelSane(nattKeepalivePacket(), 0)
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testEquals() {
+ assertEqualBothWays(nattKeepalivePacket(), nattKeepalivePacket())
+ assertNotEquals(nattKeepalivePacket(dstAddress = TEST_SRC_ADDRV4), nattKeepalivePacket())
+ assertNotEquals(nattKeepalivePacket(srcAddress = TEST_DST_ADDRV4), nattKeepalivePacket())
+ // Test src port only because dst port have to be NATT_PORT
+ assertNotEquals(nattKeepalivePacket(srcPort = TEST_PORT2), nattKeepalivePacket())
+ // Make sure the parceling test is updated if fields are added in the base class.
+ assertFieldCountEquals(5, KeepalivePacketData::class.java)
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testHashCode() {
+ assertEquals(nattKeepalivePacket().hashCode(), nattKeepalivePacket().hashCode())
+ }
+}
\ No newline at end of file
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index efea91a..9fe1883 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -48,9 +48,11 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.os.Build;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
+import androidx.core.os.BuildCompat;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
@@ -64,6 +66,13 @@
private static final String TEST_SSID = "TEST_SSID";
private static final String DIFFERENT_TEST_SSID = "DIFFERENT_TEST_SSID";
+ private boolean isAtLeastR() {
+ // BuildCompat.isAtLeastR() is used to check the Android version before releasing Android R.
+ // Build.VERSION.SDK_INT > Build.VERSION_CODES.Q is used to check the Android version after
+ // releasing Android R.
+ return BuildCompat.isAtLeastR() || Build.VERSION.SDK_INT > Build.VERSION_CODES.Q;
+ }
+
@Test
public void testMaybeMarkCapabilitiesRestricted() {
// verify EIMS is restricted
@@ -269,25 +278,36 @@
.setUids(uids)
.addCapability(NET_CAPABILITY_EIMS)
.addCapability(NET_CAPABILITY_NOT_METERED);
- netCap.setOwnerUid(123);
+ if (isAtLeastR()) {
+ netCap.setOwnerUid(123);
+ }
assertParcelingIsLossless(netCap);
netCap.setSSID(TEST_SSID);
- assertParcelSane(netCap, 15);
+ testParcelSane(netCap);
}
@Test
public void testParcelNetworkCapabilitiesWithRequestorUidAndPackageName() {
final NetworkCapabilities netCap = new NetworkCapabilities()
.addCapability(NET_CAPABILITY_INTERNET)
- .setRequestorUid(9304)
- .setRequestorPackageName("com.android.test")
.addCapability(NET_CAPABILITY_EIMS)
.addCapability(NET_CAPABILITY_NOT_METERED);
+ if (isAtLeastR()) {
+ netCap.setRequestorPackageName("com.android.test");
+ netCap.setRequestorUid(9304);
+ }
assertParcelingIsLossless(netCap);
netCap.setSSID(TEST_SSID);
- assertParcelSane(netCap, 15);
+ testParcelSane(netCap);
}
+ private void testParcelSane(NetworkCapabilities cap) {
+ if (isAtLeastR()) {
+ assertParcelSane(cap, 15);
+ } else {
+ assertParcelSane(cap, 11);
+ }
+ }
@Test
public void testOemPaid() {
diff --git a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
index 8eb5cfa..1d6c107 100644
--- a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
@@ -304,12 +304,12 @@
}
@Test
- public void testConnectivityDiagnosticsCallbackOnConnectivityReport() {
- mBinder.onConnectivityReport(createSampleConnectivityReport());
+ public void testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable() {
+ mBinder.onConnectivityReportAvailable(createSampleConnectivityReport());
// The callback will be invoked synchronously by inline executor. Immediately check the
// latch without waiting.
- verify(mCb).onConnectivityReport(eq(createSampleConnectivityReport()));
+ verify(mCb).onConnectivityReportAvailable(eq(createSampleConnectivityReport()));
}
@Test
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index 33d77d2..e71d599 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -64,15 +64,15 @@
@Test
public void testFindIndex() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 5)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1024L, 8L, 0L, 0L, 10)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 0L, 0L, 1024L, 8L, 11)
- .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 12)
- .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+ .insertEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12);
assertEquals(4, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES,
@@ -94,21 +94,21 @@
@Test
public void testFindIndexHinted() {
final NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1024L, 8L, 0L, 0L, 10)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11)
- .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12)
- .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1024L, 8L, 0L, 0L, 10)
- .addEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 0L, 0L, 1024L, 8L, 11)
- .addEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
+ .insertEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11)
- .addEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12)
- .addEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+ .insertEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 12);
// verify that we correctly find across regardless of hinting
@@ -143,27 +143,27 @@
assertEquals(0, stats.size());
assertEquals(4, stats.internalSize());
- stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 1L, 1L, 2L, 2L, 3);
- stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 2L, 2L, 2L, 2L, 4);
- stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 3L, 3L, 2L, 2L, 5);
- stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+ stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_NO, 3L, 3L, 2L, 2L, 5);
assertEquals(4, stats.size());
assertEquals(4, stats.internalSize());
- stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 4L, 40L, 4L, 40L, 7);
- stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 5L, 50L, 4L, 40L, 8);
- stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 6L, 60L, 5L, 50L, 10);
- stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 7L, 70L, 5L, 50L, 11);
- stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+ stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_NO, 7L, 70L, 5L, 50L, 11);
assertEquals(9, stats.size());
@@ -193,8 +193,8 @@
public void testCombineExisting() throws Exception {
final NetworkStats stats = new NetworkStats(TEST_START, 10);
- stats.addEntry(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 10);
- stats.addEntry(TEST_IFACE, 1001, SET_DEFAULT, 0xff, 128L, 1L, 128L, 1L, 2);
+ stats.insertEntry(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 10);
+ stats.insertEntry(TEST_IFACE, 1001, SET_DEFAULT, 0xff, 128L, 1L, 128L, 1L, 2);
stats.combineValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, -128L, -1L,
-128L, -1L, -1);
@@ -215,12 +215,12 @@
@Test
public void testSubtractIdenticalData() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
final NetworkStats after = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
final NetworkStats result = after.subtract(before);
@@ -234,12 +234,12 @@
@Test
public void testSubtractIdenticalRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
final NetworkStats after = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1025L, 9L, 2L, 1L, 15)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 3L, 1L, 1028L, 9L, 20);
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1025L, 9L, 2L, 1L, 15)
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 3L, 1L, 1028L, 9L, 20);
final NetworkStats result = after.subtract(before);
@@ -253,13 +253,13 @@
@Test
public void testSubtractNewRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12);
final NetworkStats after = new NetworkStats(TEST_START, 3)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12)
- .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 20);
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11)
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12)
+ .insertEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 20);
final NetworkStats result = after.subtract(before);
@@ -275,11 +275,11 @@
@Test
public void testSubtractMissingRows() throws Exception {
final NetworkStats before = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 0L, 0L, 0L, 0)
- .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2048L, 0L, 0L, 0L, 0);
+ .insertEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 0L, 0L, 0L, 0)
+ .insertEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2048L, 0L, 0L, 0L, 0);
final NetworkStats after = new NetworkStats(TEST_START, 1)
- .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2049L, 2L, 3L, 4L, 0);
+ .insertEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2049L, 2L, 3L, 4L, 0);
final NetworkStats result = after.subtract(before);
@@ -293,40 +293,40 @@
@Test
public void testTotalBytes() throws Exception {
final NetworkStats iface = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 128L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 256L, 0L, 0L, 0L, 0L);
+ .insertEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 128L, 0L, 0L, 0L, 0L)
+ .insertEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 256L, 0L, 0L, 0L, 0L);
assertEquals(384L, iface.getTotalBytes());
final NetworkStats uidSet = new NetworkStats(TEST_START, 3)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L)
+ .insertEntry(TEST_IFACE, 101, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L);
assertEquals(96L, uidSet.getTotalBytes());
final NetworkStats uidTag = new NetworkStats(TEST_START, 6)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L);
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L)
+ .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L)
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L);
assertEquals(64L, uidTag.getTotalBytes());
final NetworkStats uidMetered = new NetworkStats(TEST_START, 3)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
assertEquals(96L, uidMetered.getTotalBytes());
final NetworkStats uidRoaming = new NetworkStats(TEST_START, 3)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
assertEquals(96L, uidRoaming.getTotalBytes());
}
@@ -343,11 +343,11 @@
@Test
public void testGroupedByIfaceAll() throws Exception {
final NetworkStats uidStats = new NetworkStats(TEST_START, 3)
- .addEntry(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L)
- .addEntry(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_NO,
+ .insertEntry(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 128L, 8L, 0L, 2L, 20L)
- .addEntry(IFACE_ALL, 101, SET_ALL, TAG_NONE, METERED_NO, ROAMING_YES,
+ .insertEntry(IFACE_ALL, 101, SET_ALL, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L);
final NetworkStats grouped = uidStats.groupedByIface();
@@ -361,19 +361,19 @@
@Test
public void testGroupedByIface() throws Exception {
final NetworkStats uidStats = new NetworkStats(TEST_START, 7)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L)
- .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 64L, 4L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L);
final NetworkStats grouped = uidStats.groupedByIface();
@@ -390,19 +390,19 @@
@Test
public void testAddAllValues() {
final NetworkStats first = new NetworkStats(TEST_START, 5)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
+ .insertEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
final NetworkStats second = new NetworkStats(TEST_START, 2)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
+ .insertEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
first.combineAllValues(second);
@@ -421,19 +421,19 @@
@Test
public void testGetTotal() {
final NetworkStats stats = new NetworkStats(TEST_START, 7)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L)
- .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 64L, 4L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 512L,32L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L);
assertValues(stats.getTotal(null), 1408L, 88L, 0L, 2L, 20L);
@@ -459,7 +459,7 @@
assertEquals(0, after.size());
// Test 1 item stats.
- before.addEntry(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, 1L, 128L, 0L, 2L, 20L);
+ before.insertEntry(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, 1L, 128L, 0L, 2L, 20L);
after = before.clone();
after.removeUids(new int[0]);
assertEquals(1, after.size());
@@ -469,12 +469,12 @@
assertEquals(0, after.size());
// Append remaining test items.
- before.addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 2L, 64L, 0L, 2L, 20L)
- .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 4L, 32L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 16L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 8L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 4L, 0L, 0L, 0L)
- .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 64L, 2L, 0L, 0L, 0L);
+ before.insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 2L, 64L, 0L, 2L, 20L)
+ .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 4L, 32L, 0L, 0L, 0L)
+ .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 16L, 0L, 0L, 0L)
+ .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 8L, 0L, 0L, 0L)
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 4L, 0L, 0L, 0L)
+ .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 64L, 2L, 0L, 0L, 0L);
assertEquals(7, before.size());
// Test remove with empty uid list.
@@ -505,12 +505,12 @@
@Test
public void testClone() throws Exception {
final NetworkStats original = new NetworkStats(TEST_START, 5)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
- .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L);
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
+ .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L);
// make clone and mutate original
final NetworkStats clone = original.clone();
- original.addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L);
+ original.insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L);
assertEquals(3, original.size());
assertEquals(2, clone.size());
@@ -523,8 +523,8 @@
public void testAddWhenEmpty() throws Exception {
final NetworkStats red = new NetworkStats(TEST_START, -1);
final NetworkStats blue = new NetworkStats(TEST_START, 5)
- .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
- .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L);
+ .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L)
+ .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L);
// We're mostly checking that we don't crash
red.combineAllValues(blue);
@@ -537,37 +537,37 @@
final String underlyingIface = "wlan0";
final int testTag1 = 8888;
NetworkStats delta = new NetworkStats(TEST_START, 17)
- .addEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 39605L, 46L, 12259L, 55L, 0L)
- .addEntry(tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
- .addEntry(tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 72667L, 197L, 43909L, 241L, 0L)
- .addEntry(tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 9297L, 17L, 4128L, 21L, 0L)
// VPN package also uses some traffic through unprotected network.
- .addEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 4983L, 10L, 1801L, 12L, 0L)
- .addEntry(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
// Tag entries
- .addEntry(tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO,
+ .insertEntry(tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 21691L, 41L, 13820L, 51L, 0L)
- .addEntry(tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO,
+ .insertEntry(tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1281L, 2L, 665L, 2L, 0L)
// Irrelevant entries
- .addEntry(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1685L, 5L, 2070L, 6L, 0L)
// Underlying Iface entries
- .addEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 5178L, 8L, 2139L, 11L, 0L)
- .addEntry(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
- .addEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO,
+ ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
+ .insertEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 149873L, 287L, 59217L /* smaller than sum(tun0) */,
299L /* smaller than sum(tun0) */, 0L)
- .addEntry(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
- DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
+ .insertEntry(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO,
+ ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
delta.migrateTun(tunUid, tunIface, new String[]{underlyingIface});
assertEquals(20, delta.size());
@@ -635,19 +635,19 @@
final String underlyingIface = "wlan0";
NetworkStats delta = new NetworkStats(TEST_START, 9)
// 2 different apps sent/receive data via tun0.
- .addEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L)
- .addEntry(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L)
// VPN package resends data through the tunnel (with exaggerated overhead)
- .addEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 240000, 100L, 120000L, 60L, 0L)
// 1 app already has some traffic on the underlying interface, the other doesn't yet
- .addEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 1000L, 10L, 2000L, 20L, 0L)
// Traffic through the underlying interface via the vpn app.
// This test should redistribute this data correctly.
- .addEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 75500L, 37L, 130000L, 70L, 0L);
delta.migrateTun(tunUid, tunIface, new String[]{underlyingIface});
@@ -697,9 +697,9 @@
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addEntry(entry1)
- .addEntry(entry2)
- .addEntry(entry3);
+ .insertEntry(entry1)
+ .insertEntry(entry2)
+ .insertEntry(entry3);
stats.filter(UID_ALL, INTERFACES_ALL, TAG_ALL);
assertEquals(3, stats.size());
@@ -724,9 +724,9 @@
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addEntry(entry1)
- .addEntry(entry2)
- .addEntry(entry3);
+ .insertEntry(entry1)
+ .insertEntry(entry2)
+ .insertEntry(entry3);
stats.filter(testUid, INTERFACES_ALL, TAG_ALL);
assertEquals(2, stats.size());
@@ -755,10 +755,10 @@
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 4)
- .addEntry(entry1)
- .addEntry(entry2)
- .addEntry(entry3)
- .addEntry(entry4);
+ .insertEntry(entry1)
+ .insertEntry(entry2)
+ .insertEntry(entry3)
+ .insertEntry(entry4);
stats.filter(UID_ALL, new String[] { testIf1, testIf2 }, TAG_ALL);
assertEquals(3, stats.size());
@@ -778,8 +778,8 @@
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addEntry(entry1)
- .addEntry(entry2);
+ .insertEntry(entry1)
+ .insertEntry(entry2);
stats.filter(UID_ALL, new String[] { }, TAG_ALL);
assertEquals(0, stats.size());
@@ -802,9 +802,9 @@
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 3)
- .addEntry(entry1)
- .addEntry(entry2)
- .addEntry(entry3);
+ .insertEntry(entry1)
+ .insertEntry(entry2)
+ .insertEntry(entry3);
stats.filter(UID_ALL, INTERFACES_ALL, testTag);
assertEquals(2, stats.size());
@@ -831,10 +831,10 @@
DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
NetworkStats stats = new NetworkStats(TEST_START, 4)
- .addEntry(entry1)
- .addEntry(entry2)
- .addEntry(entry3)
- .addEntry(entry4);
+ .insertEntry(entry1)
+ .insertEntry(entry2)
+ .insertEntry(entry3)
+ .insertEntry(entry4);
stats.filterDebugEntries();
@@ -891,14 +891,14 @@
0 /* operations */);
final NetworkStats statsXt = new NetworkStats(TEST_START, 3)
- .addEntry(appEntry)
- .addEntry(xtRootUidEntry)
- .addEntry(otherEntry);
+ .insertEntry(appEntry)
+ .insertEntry(xtRootUidEntry)
+ .insertEntry(otherEntry);
final NetworkStats statsEbpf = new NetworkStats(TEST_START, 3)
- .addEntry(appEntry)
- .addEntry(ebpfRootUidEntry)
- .addEntry(otherEntry);
+ .insertEntry(appEntry)
+ .insertEntry(ebpfRootUidEntry)
+ .insertEntry(otherEntry);
statsXt.apply464xlatAdjustments(stackedIface, false);
statsEbpf.apply464xlatAdjustments(stackedIface, true);
@@ -945,8 +945,8 @@
0 /* operations */);
NetworkStats stats = new NetworkStats(TEST_START, 2)
- .addEntry(firstEntry)
- .addEntry(secondEntry);
+ .insertEntry(firstEntry)
+ .insertEntry(secondEntry);
// Empty map: no adjustment
stats.apply464xlatAdjustments(new ArrayMap<>(), false);
diff --git a/tests/net/java/android/net/NetworkTemplateTest.kt b/tests/net/java/android/net/NetworkTemplateTest.kt
new file mode 100644
index 0000000..5dd0fda
--- /dev/null
+++ b/tests/net/java/android/net/NetworkTemplateTest.kt
@@ -0,0 +1,155 @@
+/*
+ * 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.net
+
+import android.content.Context
+import android.net.ConnectivityManager.TYPE_MOBILE
+import android.net.ConnectivityManager.TYPE_WIFI
+import android.net.NetworkIdentity.SUBTYPE_COMBINED
+import android.net.NetworkIdentity.buildNetworkIdentity
+import android.net.NetworkStats.DEFAULT_NETWORK_ALL
+import android.net.NetworkStats.METERED_ALL
+import android.net.NetworkStats.ROAMING_ALL
+import android.net.NetworkTemplate.MATCH_MOBILE
+import android.net.NetworkTemplate.MATCH_WIFI
+import android.net.NetworkTemplate.NETWORK_TYPE_ALL
+import android.net.NetworkTemplate.buildTemplateMobileWithRatType
+import android.telephony.TelephonyManager
+import com.android.testutils.assertParcelSane
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.MockitoAnnotations
+import kotlin.test.assertFalse
+import kotlin.test.assertNotEquals
+import kotlin.test.assertTrue
+
+private const val TEST_IMSI1 = "imsi1"
+private const val TEST_IMSI2 = "imsi2"
+private const val TEST_SSID1 = "ssid1"
+
+@RunWith(JUnit4::class)
+class NetworkTemplateTest {
+ private val mockContext = mock(Context::class.java)
+
+ private fun buildMobileNetworkState(subscriberId: String): NetworkState =
+ buildNetworkState(TYPE_MOBILE, subscriberId = subscriberId)
+ private fun buildWifiNetworkState(ssid: String): NetworkState =
+ buildNetworkState(TYPE_WIFI, ssid = ssid)
+
+ private fun buildNetworkState(
+ type: Int,
+ subscriberId: String? = null,
+ ssid: String? = null
+ ): NetworkState {
+ val info = mock(NetworkInfo::class.java)
+ doReturn(type).`when`(info).type
+ doReturn(NetworkInfo.State.CONNECTED).`when`(info).state
+ val lp = LinkProperties()
+ val caps = NetworkCapabilities().apply {
+ setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false)
+ setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true)
+ }
+ return NetworkState(info, lp, caps, mock(Network::class.java), subscriberId, ssid)
+ }
+
+ private fun NetworkTemplate.assertMatches(ident: NetworkIdentity) =
+ assertTrue(matches(ident), "$this does not match $ident")
+
+ private fun NetworkTemplate.assertDoesNotMatch(ident: NetworkIdentity) =
+ assertFalse(matches(ident), "$this should match $ident")
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ }
+
+ @Test
+ fun testRatTypeGroupMatches() {
+ val stateMobile = buildMobileNetworkState(TEST_IMSI1)
+ // Build UMTS template that matches mobile identities with RAT in the same
+ // group with any IMSI. See {@link NetworkTemplate#getCollapsedRatType}.
+ val templateUmts = buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UMTS)
+ // Build normal template that matches mobile identities with any RAT and IMSI.
+ val templateAll = buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL)
+ // Build template with UNKNOWN RAT that matches mobile identities with RAT that
+ // cannot be determined.
+ val templateUnknown =
+ buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UNKNOWN)
+
+ val identUmts = buildNetworkIdentity(
+ mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_UMTS)
+ val identHsdpa = buildNetworkIdentity(
+ mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_HSDPA)
+ val identLte = buildNetworkIdentity(
+ mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_LTE)
+ val identCombined = buildNetworkIdentity(
+ mockContext, stateMobile, false, SUBTYPE_COMBINED)
+ val identImsi2 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI2),
+ false, TelephonyManager.NETWORK_TYPE_UMTS)
+ val identWifi = buildNetworkIdentity(
+ mockContext, buildWifiNetworkState(TEST_SSID1), true, 0)
+
+ // Assert that identity with the same RAT matches.
+ templateUmts.assertMatches(identUmts)
+ templateAll.assertMatches(identUmts)
+ templateUnknown.assertDoesNotMatch(identUmts)
+ // Assert that identity with the RAT within the same group matches.
+ templateUmts.assertMatches(identHsdpa)
+ templateAll.assertMatches(identHsdpa)
+ templateUnknown.assertDoesNotMatch(identHsdpa)
+ // Assert that identity with the RAT out of the same group only matches template with
+ // NETWORK_TYPE_ALL.
+ templateUmts.assertDoesNotMatch(identLte)
+ templateAll.assertMatches(identLte)
+ templateUnknown.assertDoesNotMatch(identLte)
+ // Assert that identity with combined RAT only matches with template with NETWORK_TYPE_ALL
+ // and NETWORK_TYPE_UNKNOWN.
+ templateUmts.assertDoesNotMatch(identCombined)
+ templateAll.assertMatches(identCombined)
+ templateUnknown.assertMatches(identCombined)
+ // Assert that identity with different IMSI matches.
+ templateUmts.assertMatches(identImsi2)
+ templateAll.assertMatches(identImsi2)
+ templateUnknown.assertDoesNotMatch(identImsi2)
+ // Assert that wifi identity does not match.
+ templateUmts.assertDoesNotMatch(identWifi)
+ templateAll.assertDoesNotMatch(identWifi)
+ templateUnknown.assertDoesNotMatch(identWifi)
+ }
+
+ @Test
+ fun testParcelUnparcel() {
+ val templateMobile = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1, null, null, METERED_ALL,
+ ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_LTE)
+ val templateWifi = NetworkTemplate(MATCH_WIFI, null, null, TEST_SSID1, METERED_ALL,
+ ROAMING_ALL, DEFAULT_NETWORK_ALL, 0)
+ assertParcelSane(templateMobile, 8)
+ assertParcelSane(templateWifi, 8)
+ }
+
+ // Verify NETWORK_TYPE_ALL does not conflict with TelephonyManager#NETWORK_TYPE_* constants.
+ @Test
+ fun testNetworkTypeAll() {
+ for (ratType in TelephonyManager.getAllNetworkTypes()) {
+ assertNotEquals(NETWORK_TYPE_ALL, ratType)
+ }
+ }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 671c564..4bfb51b 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -25,7 +25,6 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
-import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL;
import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
import static android.net.ConnectivityManager.NETID_UNSET;
@@ -175,6 +174,7 @@
import android.net.ProxyInfo;
import android.net.ResolverParamsParcel;
import android.net.RouteInfo;
+import android.net.RouteInfoParcel;
import android.net.SocketKeepalive;
import android.net.UidRange;
import android.net.Uri;
@@ -427,7 +427,6 @@
public Object getSystemService(String name) {
if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
- if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack;
if (Context.USER_SERVICE.equals(name)) return mUserManager;
if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager;
if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
@@ -1374,7 +1373,6 @@
@NonNull final Predicate<Intent> filter) {
final ConditionVariable cv = new ConditionVariable();
final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
- intentFilter.addAction(CONNECTIVITY_ACTION_SUPL);
final BroadcastReceiver receiver = new BroadcastReceiver() {
private int remaining = count;
public void onReceive(Context context, Intent intent) {
@@ -1422,56 +1420,28 @@
final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL,
ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
- // Send request and check that the legacy broadcast for SUPL is sent correctly.
+ // File request, withdraw it and make sure no broadcast is sent
+ final ConditionVariable cv2 = registerConnectivityBroadcast(1);
final TestNetworkCallback callback = new TestNetworkCallback();
- final ConditionVariable cv2 = registerConnectivityBroadcastThat(1,
- intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
mCm.requestNetwork(legacyRequest, callback);
callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
- waitFor(cv2);
-
- // File another request, withdraw it and make sure no broadcast is sent
- final ConditionVariable cv3 = registerConnectivityBroadcast(1);
- final TestNetworkCallback callback2 = new TestNetworkCallback();
- mCm.requestNetwork(legacyRequest, callback2);
- callback2.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
- mCm.unregisterNetworkCallback(callback2);
- assertFalse(cv3.block(800)); // 800ms long enough to at least flake if this is sent
+ mCm.unregisterNetworkCallback(callback);
+ assertFalse(cv2.block(800)); // 800ms long enough to at least flake if this is sent
// As the broadcast did not fire, the receiver was not unregistered. Do this now.
mServiceContext.clearRegisteredReceivers();
- // Withdraw the request and check that the broadcast for disconnection is sent.
- final ConditionVariable cv4 = registerConnectivityBroadcastThat(1, intent ->
- !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected()
- && intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
- mCm.unregisterNetworkCallback(callback);
- waitFor(cv4);
-
- // Re-file the request and expect the connected broadcast again
- final ConditionVariable cv5 = registerConnectivityBroadcastThat(1,
- intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL);
- final TestNetworkCallback callback3 = new TestNetworkCallback();
- mCm.requestNetwork(legacyRequest, callback3);
- callback3.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
- waitFor(cv5);
-
- // Disconnect the network and expect two disconnected broadcasts, one for SUPL and one
- // for mobile. Use a small hack to check that both have been sent, but the order is
- // not contractual.
+ // Disconnect the network and expect mobile disconnected broadcast. Use a small hack to
+ // check that has been sent.
final AtomicBoolean vanillaAction = new AtomicBoolean(false);
- final AtomicBoolean suplAction = new AtomicBoolean(false);
- final ConditionVariable cv6 = registerConnectivityBroadcastThat(2, intent -> {
+ final ConditionVariable cv3 = registerConnectivityBroadcastThat(1, intent -> {
if (intent.getAction().equals(CONNECTIVITY_ACTION)) {
vanillaAction.set(true);
- } else if (intent.getAction().equals(CONNECTIVITY_ACTION_SUPL)) {
- suplAction.set(true);
}
return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected();
});
mCellNetworkAgent.disconnect();
- waitFor(cv6);
+ waitFor(cv3);
assertTrue(vanillaAction.get());
- assertTrue(suplAction.get());
}
@Test
@@ -2464,8 +2434,8 @@
final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
mServiceContext, "testFactory", filter);
// Register the factory and don't be surprised when the default request arrives.
- testFactory.register();
testFactory.expectAddRequestsWithScores(0);
+ testFactory.register();
testFactory.waitForNetworkRequests(1);
testFactory.setScoreFilter(42);
@@ -6064,6 +6034,7 @@
verify(mBatteryStatsService).noteNetworkInterfaceType(stackedLp.getInterfaceName(),
TYPE_MOBILE);
}
+ reset(mMockNetd);
// Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
// linkproperties are cleaned up.
@@ -6115,7 +6086,6 @@
networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
-
// Clat iface comes up. Expect stacked link to be added.
clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
@@ -6701,17 +6671,45 @@
}
}
+ private void assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel) {
+ assertEquals(route.getDestination().toString(), parcel.destination);
+ assertEquals(route.getInterface(), parcel.ifName);
+ assertEquals(route.getMtu(), parcel.mtu);
+
+ switch (route.getType()) {
+ case RouteInfo.RTN_UNICAST:
+ if (route.hasGateway()) {
+ assertEquals(route.getGateway().getHostAddress(), parcel.nextHop);
+ } else {
+ assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
+ }
+ break;
+ case RouteInfo.RTN_UNREACHABLE:
+ assertEquals(INetd.NEXTHOP_UNREACHABLE, parcel.nextHop);
+ break;
+ case RouteInfo.RTN_THROW:
+ assertEquals(INetd.NEXTHOP_THROW, parcel.nextHop);
+ break;
+ default:
+ assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop);
+ break;
+ }
+ }
+
private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception {
- InOrder inOrder = inOrder(mNetworkManagementService);
+ ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
+ verify(mMockNetd, times(routes.length)).networkAddRouteParcel(eq(netId), captor.capture());
for (int i = 0; i < routes.length; i++) {
- inOrder.verify(mNetworkManagementService).addRoute(eq(netId), eq(routes[i]));
+ assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
}
}
private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception {
- InOrder inOrder = inOrder(mNetworkManagementService);
+ ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
+ verify(mMockNetd, times(routes.length)).networkRemoveRouteParcel(eq(netId),
+ captor.capture());
for (int i = 0; i < routes.length; i++) {
- inOrder.verify(mNetworkManagementService).removeRoute(eq(netId), eq(routes[i]));
+ assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i));
}
}
@@ -6789,6 +6787,26 @@
}
@Test
+ public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception {
+ final NetworkAgentInfo naiWithoutUid =
+ new NetworkAgentInfo(
+ null, null, null, null, null, new NetworkCapabilities(), 0,
+ mServiceContext, null, null, mService, null, null, null, 0);
+
+ mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+
+ try {
+ assertFalse(
+ "Mismatched uid/package name should not pass the location permission check",
+ mService.checkConnectivityDiagnosticsPermissions(
+ Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid,
+ mContext.getOpPackageName()));
+ } catch (SecurityException e) {
+ fail("checkConnectivityDiagnosticsPermissions shouldn't surface a SecurityException");
+ }
+ }
+
+ @Test
public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception {
final NetworkAgentInfo naiWithoutUid =
new NetworkAgentInfo(
@@ -6831,7 +6849,7 @@
@Test
public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception {
final NetworkCapabilities nc = new NetworkCapabilities();
- nc.setAdministratorUids(Arrays.asList(Process.myUid()));
+ nc.setAdministratorUids(new int[] {Process.myUid()});
final NetworkAgentInfo naiWithUid =
new NetworkAgentInfo(
null, null, null, null, null, nc, 0, mServiceContext, null, null,
@@ -6853,7 +6871,7 @@
public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception {
final NetworkCapabilities nc = new NetworkCapabilities();
nc.setOwnerUid(Process.myUid());
- nc.setAdministratorUids(Arrays.asList(Process.myUid()));
+ nc.setAdministratorUids(new int[] {Process.myUid()});
final NetworkAgentInfo naiWithUid =
new NetworkAgentInfo(
null, null, null, null, null, nc, 0, mServiceContext, null, null,
@@ -6894,18 +6912,19 @@
}
@Test
- public void testConnectivityDiagnosticsCallbackOnConnectivityReport() throws Exception {
+ public void testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable()
+ throws Exception {
setUpConnectivityDiagnosticsCallback();
// Block until all other events are done processing.
HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS);
// Verify onConnectivityReport fired
- verify(mConnectivityDiagnosticsCallback).onConnectivityReport(
+ verify(mConnectivityDiagnosticsCallback).onConnectivityReportAvailable(
argThat(report -> {
final NetworkCapabilities nc = report.getNetworkCapabilities();
return nc.getUids() == null
- && nc.getAdministratorUids().isEmpty()
+ && nc.getAdministratorUids().length == 0
&& nc.getOwnerUid() == Process.INVALID_UID;
}));
}
@@ -6926,7 +6945,7 @@
argThat(report -> {
final NetworkCapabilities nc = report.getNetworkCapabilities();
return nc.getUids() == null
- && nc.getAdministratorUids().isEmpty()
+ && nc.getAdministratorUids().length == 0
&& nc.getOwnerUid() == Process.INVALID_UID;
}));
}
@@ -6956,4 +6975,60 @@
verify(mConnectivityDiagnosticsCallback)
.onNetworkConnectivityReported(eq(n), eq(noConnectivity));
}
+
+ @Test
+ public void testRouteAddDeleteUpdate() throws Exception {
+ final NetworkRequest request = new NetworkRequest.Builder().build();
+ final TestNetworkCallback networkCallback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(request, networkCallback);
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ reset(mMockNetd);
+ mCellNetworkAgent.connect(false);
+ networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+ final int netId = mCellNetworkAgent.getNetwork().netId;
+
+ final String iface = "rmnet_data0";
+ final InetAddress gateway = InetAddress.getByName("fe80::5678");
+ RouteInfo direct = RouteInfo.makeHostRoute(gateway, iface);
+ RouteInfo rio1 = new RouteInfo(new IpPrefix("2001:db8:1::/48"), gateway, iface);
+ RouteInfo rio2 = new RouteInfo(new IpPrefix("2001:db8:2::/48"), gateway, iface);
+ RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, gateway, iface);
+ RouteInfo defaultWithMtu = new RouteInfo(null, gateway, iface, RouteInfo.RTN_UNICAST,
+ 1280 /* mtu */);
+
+ // Send LinkProperties and check that we ask netd to add routes.
+ LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName(iface);
+ lp.addRoute(direct);
+ lp.addRoute(rio1);
+ lp.addRoute(defaultRoute);
+ mCellNetworkAgent.sendLinkProperties(lp);
+ networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, x -> x.getRoutes().size() == 3);
+
+ assertRoutesAdded(netId, direct, rio1, defaultRoute);
+ reset(mMockNetd);
+
+ // Send updated LinkProperties and check that we ask netd to add, remove, update routes.
+ assertTrue(lp.getRoutes().contains(defaultRoute));
+ lp.removeRoute(rio1);
+ lp.addRoute(rio2);
+ lp.addRoute(defaultWithMtu);
+ // Ensure adding the same route with a different MTU replaces the previous route.
+ assertFalse(lp.getRoutes().contains(defaultRoute));
+ assertTrue(lp.getRoutes().contains(defaultWithMtu));
+
+ mCellNetworkAgent.sendLinkProperties(lp);
+ networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
+ x -> x.getRoutes().contains(rio2));
+
+ assertRoutesRemoved(netId, rio1);
+ assertRoutesAdded(netId, rio2);
+
+ ArgumentCaptor<RouteInfoParcel> captor = ArgumentCaptor.forClass(RouteInfoParcel.class);
+ verify(mMockNetd).networkUpdateRouteParcel(eq(netId), captor.capture());
+ assertRouteInfoParcelMatches(defaultWithMtu, captor.getValue());
+
+
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
index 8f90f13..551498f 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
@@ -319,33 +319,33 @@
assertEntry(18322, 75, 15031, 75, history.getValues(i++, null));
assertEntry(527798, 761, 78570, 652, history.getValues(i++, null));
assertEntry(527797, 760, 78570, 651, history.getValues(i++, null));
- assertEntry(10747, 50, 16838, 55, history.getValues(i++, null));
- assertEntry(10747, 49, 16838, 54, history.getValues(i++, null));
+ assertEntry(10747, 50, 16839, 55, history.getValues(i++, null));
+ assertEntry(10747, 49, 16837, 54, history.getValues(i++, null));
assertEntry(89191, 151, 18021, 140, history.getValues(i++, null));
assertEntry(89190, 150, 18020, 139, history.getValues(i++, null));
- assertEntry(3821, 22, 4525, 26, history.getValues(i++, null));
- assertEntry(3820, 22, 4524, 26, history.getValues(i++, null));
- assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
- assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
+ assertEntry(3821, 23, 4525, 26, history.getValues(i++, null));
+ assertEntry(3820, 21, 4524, 26, history.getValues(i++, null));
+ assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
+ assertEntry(8289, 36, 6864, 39, history.getValues(i++, null));
+ assertEntry(8289, 34, 6862, 37, history.getValues(i++, null));
assertEntry(113914, 174, 18364, 157, history.getValues(i++, null));
assertEntry(113913, 173, 18364, 157, history.getValues(i++, null));
- assertEntry(11378, 49, 9261, 49, history.getValues(i++, null));
- assertEntry(11377, 48, 9261, 49, history.getValues(i++, null));
- assertEntry(201765, 328, 41808, 291, history.getValues(i++, null));
- assertEntry(201765, 328, 41807, 290, history.getValues(i++, null));
- assertEntry(106106, 218, 39917, 201, history.getValues(i++, null));
- assertEntry(106105, 217, 39917, 201, history.getValues(i++, null));
+ assertEntry(11378, 49, 9261, 50, history.getValues(i++, null));
+ assertEntry(11377, 48, 9261, 48, history.getValues(i++, null));
+ assertEntry(201766, 328, 41808, 291, history.getValues(i++, null));
+ assertEntry(201764, 328, 41807, 290, history.getValues(i++, null));
+ assertEntry(106106, 219, 39918, 202, history.getValues(i++, null));
+ assertEntry(106105, 216, 39916, 200, history.getValues(i++, null));
assertEquals(history.size(), i);
// Slice from middle should be untouched
history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS,
TIME_B + HOUR_IN_MILLIS); i = 0;
- assertEntry(3821, 22, 4525, 26, history.getValues(i++, null));
- assertEntry(3820, 22, 4524, 26, history.getValues(i++, null));
- assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(3821, 23, 4525, 26, history.getValues(i++, null));
+ assertEntry(3820, 21, 4524, 26, history.getValues(i++, null));
+ assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
assertEquals(history.size(), i);
}
@@ -373,25 +373,25 @@
assertEntry(527797, 760, 78570, 651, history.getValues(i++, null));
// Cycle point; start data normalization
assertEntry(7507, 0, 11763, 0, history.getValues(i++, null));
- assertEntry(7507, 0, 11763, 0, history.getValues(i++, null));
+ assertEntry(7507, 0, 11762, 0, history.getValues(i++, null));
assertEntry(62309, 0, 12589, 0, history.getValues(i++, null));
assertEntry(62309, 0, 12588, 0, history.getValues(i++, null));
assertEntry(2669, 0, 3161, 0, history.getValues(i++, null));
assertEntry(2668, 0, 3160, 0, history.getValues(i++, null));
// Anchor point; end data normalization
- assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
- assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
+ assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
+ assertEntry(8289, 36, 6864, 39, history.getValues(i++, null));
+ assertEntry(8289, 34, 6862, 37, history.getValues(i++, null));
assertEntry(113914, 174, 18364, 157, history.getValues(i++, null));
assertEntry(113913, 173, 18364, 157, history.getValues(i++, null));
// Cycle point
- assertEntry(11378, 49, 9261, 49, history.getValues(i++, null));
- assertEntry(11377, 48, 9261, 49, history.getValues(i++, null));
- assertEntry(201765, 328, 41808, 291, history.getValues(i++, null));
- assertEntry(201765, 328, 41807, 290, history.getValues(i++, null));
- assertEntry(106106, 218, 39917, 201, history.getValues(i++, null));
- assertEntry(106105, 217, 39917, 201, history.getValues(i++, null));
+ assertEntry(11378, 49, 9261, 50, history.getValues(i++, null));
+ assertEntry(11377, 48, 9261, 48, history.getValues(i++, null));
+ assertEntry(201766, 328, 41808, 291, history.getValues(i++, null));
+ assertEntry(201764, 328, 41807, 290, history.getValues(i++, null));
+ assertEntry(106106, 219, 39918, 202, history.getValues(i++, null));
+ assertEntry(106105, 216, 39916, 200, history.getValues(i++, null));
assertEquals(history.size(), i);
// Slice from middle should be augmented
@@ -399,8 +399,8 @@
TIME_B + HOUR_IN_MILLIS); i = 0;
assertEntry(2669, 0, 3161, 0, history.getValues(i++, null));
assertEntry(2668, 0, 3160, 0, history.getValues(i++, null));
- assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
assertEquals(history.size(), i);
}
@@ -427,34 +427,34 @@
assertEntry(527798, 761, 78570, 652, history.getValues(i++, null));
assertEntry(527797, 760, 78570, 651, history.getValues(i++, null));
// Cycle point; start data normalization
- assertEntry(15015, 0, 23526, 0, history.getValues(i++, null));
- assertEntry(15015, 0, 23526, 0, history.getValues(i++, null));
+ assertEntry(15015, 0, 23527, 0, history.getValues(i++, null));
+ assertEntry(15015, 0, 23524, 0, history.getValues(i++, null));
assertEntry(124619, 0, 25179, 0, history.getValues(i++, null));
assertEntry(124618, 0, 25177, 0, history.getValues(i++, null));
assertEntry(5338, 0, 6322, 0, history.getValues(i++, null));
assertEntry(5337, 0, 6320, 0, history.getValues(i++, null));
// Anchor point; end data normalization
- assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
- assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
+ assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
+ assertEntry(8289, 36, 6864, 39, history.getValues(i++, null));
+ assertEntry(8289, 34, 6862, 37, history.getValues(i++, null));
assertEntry(113914, 174, 18364, 157, history.getValues(i++, null));
assertEntry(113913, 173, 18364, 157, history.getValues(i++, null));
// Cycle point
- assertEntry(11378, 49, 9261, 49, history.getValues(i++, null));
- assertEntry(11377, 48, 9261, 49, history.getValues(i++, null));
- assertEntry(201765, 328, 41808, 291, history.getValues(i++, null));
- assertEntry(201765, 328, 41807, 290, history.getValues(i++, null));
- assertEntry(106106, 218, 39917, 201, history.getValues(i++, null));
- assertEntry(106105, 217, 39917, 201, history.getValues(i++, null));
+ assertEntry(11378, 49, 9261, 50, history.getValues(i++, null));
+ assertEntry(11377, 48, 9261, 48, history.getValues(i++, null));
+ assertEntry(201766, 328, 41808, 291, history.getValues(i++, null));
+ assertEntry(201764, 328, 41807, 290, history.getValues(i++, null));
+ assertEntry(106106, 219, 39918, 202, history.getValues(i++, null));
+ assertEntry(106105, 216, 39916, 200, history.getValues(i++, null));
// Slice from middle should be augmented
history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS,
TIME_B + HOUR_IN_MILLIS); i = 0;
assertEntry(5338, 0, 6322, 0, history.getValues(i++, null));
assertEntry(5337, 0, 6320, 0, history.getValues(i++, null));
- assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
- assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(91686, 159, 18576, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18574, 146, history.getValues(i++, null));
assertEquals(history.size(), i);
}
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
index f0e5774..a6f7a36 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -240,7 +240,7 @@
// Baseline
NetworkStats xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */)
- .addIfaceValues(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L);
+ .insertEntry(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L);
NetworkStats uidSnapshot = null;
mStatsObservers.updateStats(
@@ -264,14 +264,14 @@
// Baseline
NetworkStats xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */)
- .addIfaceValues(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L);
+ .insertEntry(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L);
NetworkStats uidSnapshot = null;
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */)
- .addIfaceValues(TEST_IFACE, BASE_BYTES + 1024L, 10L, BASE_BYTES + 2048L, 20L);
+ .insertEntry(TEST_IFACE, BASE_BYTES + 1024L, 10L, BASE_BYTES + 2048L, 20L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
waitForObserverToIdle();
@@ -294,14 +294,14 @@
// Baseline
NetworkStats xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */)
- .addIfaceValues(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L);
+ .insertEntry(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L);
NetworkStats uidSnapshot = null;
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
xtSnapshot = new NetworkStats(TEST_START + MINUTE_IN_MILLIS, 1 /* initialSize */)
- .addIfaceValues(TEST_IFACE, BASE_BYTES + THRESHOLD_BYTES, 12L,
+ .insertEntry(TEST_IFACE, BASE_BYTES + THRESHOLD_BYTES, 12L,
BASE_BYTES + THRESHOLD_BYTES, 22L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
@@ -326,14 +326,14 @@
// Baseline
NetworkStats xtSnapshot = null;
NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
@@ -359,14 +359,14 @@
// Baseline
NetworkStats xtSnapshot = null;
NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
@@ -391,14 +391,14 @@
// Baseline
NetworkStats xtSnapshot = null;
NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
@@ -424,14 +424,14 @@
// Baseline
NetworkStats xtSnapshot = null;
NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
- .addEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
+ .insertEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
mStatsObservers.updateStats(
xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START);
// Delta
uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
- .addEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
+ .insertEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
ROAMING_NO, DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
mStatsObservers.updateStats(
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 36deca3..6e63313 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -42,6 +42,7 @@
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
+import static android.net.NetworkTemplate.buildTemplateMobileWithRatType;
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.net.TrafficStats.UID_REMOVED;
@@ -60,11 +61,13 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
@@ -92,6 +95,8 @@
import android.os.Messenger;
import android.os.PowerManager;
import android.os.SimpleClock;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import androidx.test.InstrumentationRegistry;
@@ -163,11 +168,14 @@
private @Mock NetworkStatsSettings mSettings;
private @Mock IBinder mBinder;
private @Mock AlarmManager mAlarmManager;
+ private @Mock TelephonyManager mTelephonyManager;
private HandlerThread mHandlerThread;
private NetworkStatsService mService;
private INetworkStatsSession mSession;
private INetworkManagementEventObserver mNetworkObserver;
+ @Nullable
+ private PhoneStateListener mPhoneStateListener;
private final Clock mClock = new SimpleClock(ZoneOffset.UTC) {
@Override
@@ -195,7 +203,7 @@
mHandlerThread = new HandlerThread("HandlerThread");
final NetworkStatsService.Dependencies deps = makeDependencies();
mService = new NetworkStatsService(mServiceContext, mNetManager, mAlarmManager, wakeLock,
- mClock, mServiceContext.getSystemService(TelephonyManager.class), mSettings,
+ mClock, mTelephonyManager, mSettings,
mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir), deps);
mElapsedRealtime = 0L;
@@ -216,6 +224,12 @@
ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
verify(mNetManager).registerObserver(networkObserver.capture());
mNetworkObserver = networkObserver.getValue();
+
+ // Capture the phone state listener that created by service.
+ final ArgumentCaptor<PhoneStateListener> phoneStateListenerCaptor =
+ ArgumentCaptor.forClass(PhoneStateListener.class);
+ verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(), anyInt());
+ mPhoneStateListener = phoneStateListenerCaptor.getValue();
}
@NonNull
@@ -263,7 +277,7 @@
incrementCurrentTime(HOUR_IN_MILLIS);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L));
+ .insertEntry(TEST_IFACE, 1024L, 1L, 2048L, 2L));
expectNetworkStatsUidDetail(buildEmptyStats());
forcePollAndWaitForIdle();
@@ -276,7 +290,7 @@
incrementCurrentTime(DAY_IN_MILLIS);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 4096L, 4L, 8192L, 8L));
+ .insertEntry(TEST_IFACE, 4096L, 4L, 8192L, 8L));
expectNetworkStatsUidDetail(buildEmptyStats());
forcePollAndWaitForIdle();
@@ -306,13 +320,13 @@
incrementCurrentTime(HOUR_IN_MILLIS);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 1024L, 8L, 2048L, 16L));
+ .insertEntry(TEST_IFACE, 1024L, 8L, 2048L, 16L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
- .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L));
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L)
+ .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L));
mService.setUidForeground(UID_RED, false);
mService.incrementOperationCount(UID_RED, 0xFAAD, 4);
mService.setUidForeground(UID_RED, true);
@@ -375,7 +389,7 @@
incrementCurrentTime(2 * HOUR_IN_MILLIS);
expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS);
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 512L, 4L, 512L, 4L));
+ .insertEntry(TEST_IFACE, 512L, 4L, 512L, 4L));
expectNetworkStatsUidDetail(buildEmptyStats());
forcePollAndWaitForIdle();
@@ -415,11 +429,11 @@
incrementCurrentTime(HOUR_IN_MILLIS);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L));
+ .insertEntry(TEST_IFACE, 2048L, 16L, 512L, 4L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
- .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
+ .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 10);
forcePollAndWaitForIdle();
@@ -437,11 +451,11 @@
expectDefaultSettings();
states = new NetworkState[] {buildMobile3gState(IMSI_2)};
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L));
+ .insertEntry(TEST_IFACE, 2048L, 16L, 512L, 4L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
- .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
+ .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
forcePollAndWaitForIdle();
@@ -451,12 +465,12 @@
incrementCurrentTime(HOUR_IN_MILLIS);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 2176L, 17L, 1536L, 12L));
+ .insertEntry(TEST_IFACE, 2176L, 17L, 1536L, 12L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
- .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 640L, 5L, 1024L, 8L, 0L)
- .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L));
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
+ .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 640L, 5L, 1024L, 8L, 0L)
+ .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L));
mService.incrementOperationCount(UID_BLUE, 0xFAAD, 10);
forcePollAndWaitForIdle();
@@ -488,12 +502,13 @@
incrementCurrentTime(HOUR_IN_MILLIS);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 4128L, 258L, 544L, 34L));
+ .insertEntry(TEST_IFACE, 4128L, 258L, 544L, 34L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
- .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
- .addEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
+ .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE,
+ 4096L, 258L, 512L, 32L, 0L)
+ .insertEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
mService.incrementOperationCount(UID_RED, 0xFAAD, 10);
forcePollAndWaitForIdle();
@@ -509,12 +524,13 @@
// special "removed" bucket.
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 4128L, 258L, 544L, 34L));
+ .insertEntry(TEST_IFACE, 4128L, 258L, 544L, 34L));
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
- .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L)
- .addEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L)
+ .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE,
+ 4096L, 258L, 512L, 32L, 0L)
+ .insertEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L));
final Intent intent = new Intent(ACTION_UID_REMOVED);
intent.putExtra(EXTRA_UID, UID_BLUE);
mServiceContext.sendBroadcast(intent);
@@ -532,7 +548,7 @@
}
@Test
- public void testUid3g4gCombinedByTemplate() throws Exception {
+ public void testUid3gWimaxCombinedByTemplate() throws Exception {
// pretend that network comes online
expectDefaultSettings();
NetworkState[] states = new NetworkState[] {buildMobile3gState(IMSI_1)};
@@ -546,8 +562,8 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 5);
forcePollAndWaitForIdle();
@@ -556,14 +572,14 @@
assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 8L, 1024L, 8L, 5);
- // now switch over to 4g network
+ // now switch over to wimax network
incrementCurrentTime(HOUR_IN_MILLIS);
expectDefaultSettings();
- states = new NetworkState[] {buildMobile4gState(TEST_IFACE2)};
+ states = new NetworkState[] {buildWimaxState(TEST_IFACE2)};
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
forcePollAndWaitForIdle();
@@ -574,10 +590,10 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
- .addEntry(TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
- .addEntry(TEST_IFACE2, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L));
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
+ .insertEntry(TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L)
+ .insertEntry(TEST_IFACE2, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L));
mService.incrementOperationCount(UID_RED, 0xFAAD, 5);
forcePollAndWaitForIdle();
@@ -587,6 +603,89 @@
}
@Test
+ public void testMobileStatsByRatType() throws Exception {
+ final NetworkTemplate template3g =
+ buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UMTS);
+ final NetworkTemplate template4g =
+ buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_LTE);
+ final NetworkTemplate template5g =
+ buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_NR);
+ final NetworkState[] states = new NetworkState[]{buildMobile3gState(IMSI_1)};
+
+ // 3G network comes online.
+ expectNetworkStatsSummary(buildEmptyStats());
+ expectNetworkStatsUidDetail(buildEmptyStats());
+
+ setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS);
+ mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+ new VpnInfo[0]);
+
+ // Create some traffic.
+ incrementCurrentTime(MINUTE_IN_MILLIS);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
+ 12L, 18L, 14L, 1L, 0L)));
+ forcePollAndWaitForIdle();
+
+ // Verify 3g templates gets stats.
+ assertUidTotal(sTemplateImsi1, UID_RED, 12L, 18L, 14L, 1L, 0);
+ assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0);
+ assertUidTotal(template4g, UID_RED, 0L, 0L, 0L, 0L, 0);
+ assertUidTotal(template5g, UID_RED, 0L, 0L, 0L, 0L, 0);
+
+ // 4G network comes online.
+ incrementCurrentTime(MINUTE_IN_MILLIS);
+ setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_LTE);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
+ // Append more traffic on existing 3g stats entry.
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
+ 16L, 22L, 17L, 2L, 0L))
+ // Add entry that is new on 4g.
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE,
+ 33L, 27L, 8L, 10L, 1L)));
+ forcePollAndWaitForIdle();
+
+ // Verify ALL_MOBILE template gets all. 3g template counters do not increase.
+ assertUidTotal(sTemplateImsi1, UID_RED, 49L, 49L, 25L, 12L, 1);
+ assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0);
+ // Verify 4g template counts appended stats on existing entry and newly created entry.
+ assertUidTotal(template4g, UID_RED, 4L + 33L, 4L + 27L, 3L + 8L, 1L + 10L, 1);
+ // Verify 5g template doesn't get anything since no traffic is generated on 5g.
+ assertUidTotal(template5g, UID_RED, 0L, 0L, 0L, 0L, 0);
+
+ // 5g network comes online.
+ incrementCurrentTime(MINUTE_IN_MILLIS);
+ setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_NR);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
+ // Existing stats remains.
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
+ 16L, 22L, 17L, 2L, 0L))
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE,
+ 33L, 27L, 8L, 10L, 1L))
+ // Add some traffic on 5g.
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE,
+ 5L, 13L, 31L, 9L, 2L)));
+ forcePollAndWaitForIdle();
+
+ // Verify ALL_MOBILE template gets all.
+ assertUidTotal(sTemplateImsi1, UID_RED, 54L, 62L, 56L, 21L, 3);
+ // 3g/4g template counters do not increase.
+ assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0);
+ assertUidTotal(template4g, UID_RED, 4L + 33L, 4L + 27L, 3L + 8L, 1L + 10L, 1);
+ // Verify 5g template gets the 5g count.
+ assertUidTotal(template5g, UID_RED, 5L, 13L, 31L, 9L, 2);
+ }
+
+ // TODO: support per IMSI state
+ private void setMobileRatTypeAndWaitForIdle(int ratType) {
+ final ServiceState mockSs = mock(ServiceState.class);
+ when(mockSs.getDataNetworkType()).thenReturn(ratType);
+ mPhoneStateListener.onServiceStateChanged(mockSs);
+
+ HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT);
+ }
+
+ @Test
public void testSummaryForAllUid() throws Exception {
// pretend that network comes online
expectDefaultSettings();
@@ -601,9 +700,9 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
- .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L));
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
+ .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
forcePollAndWaitForIdle();
@@ -618,9 +717,10 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
- .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0L));
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L)
+ .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE,
+ 2048L, 16L, 1024L, 8L, 0L));
forcePollAndWaitForIdle();
// first verify entire history present
@@ -664,9 +764,9 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addEntry(entry1)
- .addEntry(entry2)
- .addEntry(entry3));
+ .insertEntry(entry1)
+ .insertEntry(entry2)
+ .insertEntry(entry3));
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
NetworkStats stats = mService.getDetailedUidStats(INTERFACES_ALL);
@@ -714,11 +814,11 @@
.thenReturn(augmentedIfaceFilter);
when(mStatsFactory.readNetworkStatsDetail(eq(UID_ALL), any(), eq(TAG_ALL)))
.thenReturn(new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(uidStats));
+ .insertEntry(uidStats));
when(mNetManager.getNetworkStatsTethering(STATS_PER_UID))
.thenReturn(new NetworkStats(getElapsedRealtime(), 2)
- .addEntry(tetheredStats1)
- .addEntry(tetheredStats2));
+ .insertEntry(tetheredStats1)
+ .insertEntry(tetheredStats2));
NetworkStats stats = mService.getDetailedUidStats(ifaceFilter);
@@ -755,8 +855,8 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L));
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
forcePollAndWaitForIdle();
@@ -770,10 +870,10 @@
expectDefaultSettings();
expectNetworkStatsSummary(buildEmptyStats());
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L));
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L)
+ .insertEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L));
mService.setUidForeground(UID_RED, true);
mService.incrementOperationCount(UID_RED, 0xFAAD, 1);
@@ -814,9 +914,9 @@
// and DEFAULT_NETWORK_YES, because these three properties aren't tracked at that layer.
// We layer them on top by inspecting the iface properties.
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0L));
mService.incrementOperationCount(UID_RED, 0xF00D, 1);
@@ -853,9 +953,9 @@
// ROAMING_NO, because metered and roaming isn't tracked at that layer. We layer it
// on top by inspecting the iface properties.
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO,
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO,
DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 0L)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_NO,
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_NO,
DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0L));
forcePollAndWaitForIdle();
@@ -888,17 +988,17 @@
// Traffic seen by kernel counters (includes software tethering).
final NetworkStats ifaceStats = new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 1536L, 12L, 384L, 3L);
+ .insertEntry(TEST_IFACE, 1536L, 12L, 384L, 3L);
// Hardware tethering traffic, not seen by kernel counters.
final NetworkStats tetherStatsHardware = new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 512L, 4L, 128L, 1L);
+ .insertEntry(TEST_IFACE, 512L, 4L, 128L, 1L);
// Traffic for UID_RED.
final NetworkStats uidStats = new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L);
+ .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L);
// All tethering traffic, both hardware and software.
final NetworkStats tetherStats = new NetworkStats(getElapsedRealtime(), 1)
- .addEntry(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L,
+ .insertEntry(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L,
0L);
expectNetworkStatsSummary(ifaceStats, tetherStatsHardware);
@@ -957,7 +1057,7 @@
incrementCurrentTime(HOUR_IN_MILLIS);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L));
+ .insertEntry(TEST_IFACE, 1024L, 1L, 2048L, 2L));
expectNetworkStatsUidDetail(buildEmptyStats());
forcePollAndWaitForIdle();
@@ -972,7 +1072,7 @@
incrementCurrentTime(DAY_IN_MILLIS);
expectDefaultSettings();
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
- .addIfaceValues(TEST_IFACE, 4096000L, 4L, 8192000L, 8L));
+ .insertEntry(TEST_IFACE, 4096000L, 4L, 8192000L, 8L));
expectNetworkStatsUidDetail(buildEmptyStats());
forcePollAndWaitForIdle();
@@ -1026,18 +1126,18 @@
mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
// Verifies that one requestStatsUpdate will be called during iface update.
- provider.expectStatsUpdate(0 /* unused */);
+ provider.expectOnRequestStatsUpdate(0 /* unused */);
// Create some initial traffic and report to the service.
incrementCurrentTime(HOUR_IN_MILLIS);
final NetworkStats expectedStats = new NetworkStats(0L, 1)
- .addValues(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT,
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT,
TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES,
128L, 2L, 128L, 2L, 1L))
- .addValues(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT,
+ .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT,
0xF00D, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES,
64L, 1L, 64L, 1L, 1L));
- cb.onStatsUpdated(0 /* unused */, expectedStats, expectedStats);
+ cb.notifyStatsUpdated(0 /* unused */, expectedStats, expectedStats);
// Make another empty mutable stats object. This is necessary since the new NetworkStats
// object will be used to compare with the old one in NetworkStatsRecoder, two of them
@@ -1047,8 +1147,8 @@
forcePollAndWaitForIdle();
// Verifies that one requestStatsUpdate and setAlert will be called during polling.
- provider.expectStatsUpdate(0 /* unused */);
- provider.expectSetAlert(MB_IN_BYTES);
+ provider.expectOnRequestStatsUpdate(0 /* unused */);
+ provider.expectOnSetAlert(MB_IN_BYTES);
// Verifies that service recorded history, does not verify uid tag part.
assertUidTotal(sTemplateWifi, UID_RED, 128L, 2L, 128L, 2L, 1);
@@ -1082,13 +1182,13 @@
assertNotNull(cb);
// Simulates alert quota of the provider has been reached.
- cb.onAlertReached();
+ cb.notifyAlertReached();
HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT);
// Verifies that polling is triggered by alert reached.
- provider.expectStatsUpdate(0 /* unused */);
+ provider.expectOnRequestStatsUpdate(0 /* unused */);
// Verifies that global alert will be re-armed.
- provider.expectSetAlert(MB_IN_BYTES);
+ provider.expectOnSetAlert(MB_IN_BYTES);
}
private static File getBaseDir(File statsDir) {
@@ -1194,6 +1294,7 @@
when(mSettings.getPollInterval()).thenReturn(HOUR_IN_MILLIS);
when(mSettings.getPollDelay()).thenReturn(0L);
when(mSettings.getSampleEnabled()).thenReturn(true);
+ when(mSettings.getCombineSubtypeEnabled()).thenReturn(false);
final Config config = new Config(bucketDuration, deleteAge, deleteAge);
when(mSettings.getDevConfig()).thenReturn(config);
@@ -1239,6 +1340,7 @@
final NetworkCapabilities capabilities = new NetworkCapabilities();
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !isMetered);
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true);
+ capabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
return new NetworkState(info, prop, capabilities, WIFI_NETWORK, null, TEST_SSID);
}
@@ -1256,10 +1358,11 @@
final NetworkCapabilities capabilities = new NetworkCapabilities();
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false);
capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming);
+ capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
return new NetworkState(info, prop, capabilities, MOBILE_NETWORK, subscriberId, null);
}
- private static NetworkState buildMobile4gState(String iface) {
+ private static NetworkState buildWimaxState(@NonNull String iface) {
final NetworkInfo info = new NetworkInfo(TYPE_WIMAX, 0, null, null);
info.setDetailedState(DetailedState.CONNECTED, null, null);
final LinkProperties prop = new LinkProperties();
diff --git a/wifi/Android.bp b/wifi/Android.bp
index f4d2881..fbafa07 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -46,6 +46,7 @@
// TODO(b/146011398) package android.net.wifi is now split amongst 2 jars: framework.jar and
// framework-wifi.jar. This is not a good idea, should move WifiNetworkScoreCache
// to a separate package.
+ "java/android/net/wifi/SoftApConfToXmlMigrationUtil.java",
"java/android/net/wifi/WifiNetworkScoreCache.java",
"java/android/net/wifi/WifiMigration.java",
"java/android/net/wifi/nl80211/*.java",
@@ -72,8 +73,7 @@
// classes before they are renamed.
java_library {
name: "framework-wifi-pre-jarjar",
- // TODO(b/146757305): sdk_version should be "module_lib_current"
- sdk_version: "core_current",
+ sdk_version: "module_current",
static_libs: [
"framework-wifi-util-lib",
"android.hardware.wifi-V1.0-java-constants",
@@ -83,9 +83,6 @@
"unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
"unsupportedappusage-annotation", // for dalvik.annotation.compat.UnsupportedAppUsage
"framework-telephony-stubs",
- // TODO(b/146757305): should be unnecessary once
- // sdk_version="module_lib_current"
- "android_system_stubs_current",
],
srcs: [
":framework-wifi-updatable-sources",
@@ -98,21 +95,12 @@
"//frameworks/opt/net/wifi/service",
"//frameworks/opt/net/wifi/tests/wifitests",
],
-
- // TODO(b/146757305): should be unnecessary once
- // sdk_version="module_lib_current"
- aidl: {
- include_dirs: [
- "frameworks/base/core/java",
- ],
- },
}
// post-jarjar version of framework-wifi
java_library {
name: "framework-wifi",
- // TODO(b/146757305): sdk_version should be "module_lib_current"
- sdk_version: "core_current",
+ sdk_version: "module_current",
static_libs: [
"framework-wifi-pre-jarjar",
],
diff --git a/wifi/api/current.txt b/wifi/api/current.txt
new file mode 100644
index 0000000..1b62ec1
--- /dev/null
+++ b/wifi/api/current.txt
@@ -0,0 +1,1199 @@
+// Signature format: 2.0
+package android.net.wifi {
+
+ public abstract class EasyConnectStatusCallback {
+ field public static final int EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION = -2; // 0xfffffffe
+ field public static final int EASY_CONNECT_EVENT_FAILURE_BUSY = -5; // 0xfffffffb
+ field public static final int EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK = -10; // 0xfffffff6
+ field public static final int EASY_CONNECT_EVENT_FAILURE_CONFIGURATION = -4; // 0xfffffffc
+ field public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION = -11; // 0xfffffff5
+ field public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION = -12; // 0xfffffff4
+ field public static final int EASY_CONNECT_EVENT_FAILURE_GENERIC = -7; // 0xfffffff9
+ field public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK = -9; // 0xfffffff7
+ field public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_URI = -1; // 0xffffffff
+ field public static final int EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE = -3; // 0xfffffffd
+ field public static final int EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED = -8; // 0xfffffff8
+ field public static final int EASY_CONNECT_EVENT_FAILURE_TIMEOUT = -6; // 0xfffffffa
+ }
+
+ public class ScanResult implements android.os.Parcelable {
+ ctor public ScanResult(@NonNull android.net.wifi.ScanResult);
+ ctor public ScanResult();
+ method public int describeContents();
+ method @NonNull public java.util.List<android.net.wifi.ScanResult.InformationElement> getInformationElements();
+ method public int getWifiStandard();
+ method public boolean is80211mcResponder();
+ method public boolean isPasspointNetwork();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public String BSSID;
+ field public static final int CHANNEL_WIDTH_160MHZ = 3; // 0x3
+ field public static final int CHANNEL_WIDTH_20MHZ = 0; // 0x0
+ field public static final int CHANNEL_WIDTH_40MHZ = 1; // 0x1
+ field public static final int CHANNEL_WIDTH_80MHZ = 2; // 0x2
+ field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; // 0x4
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.ScanResult> CREATOR;
+ field public String SSID;
+ field public static final int WIFI_STANDARD_11AC = 5; // 0x5
+ field public static final int WIFI_STANDARD_11AX = 6; // 0x6
+ field public static final int WIFI_STANDARD_11N = 4; // 0x4
+ field public static final int WIFI_STANDARD_LEGACY = 1; // 0x1
+ field public static final int WIFI_STANDARD_UNKNOWN = 0; // 0x0
+ field public String capabilities;
+ field public int centerFreq0;
+ field public int centerFreq1;
+ field public int channelWidth;
+ field public int frequency;
+ field public int level;
+ field public CharSequence operatorFriendlyName;
+ field public long timestamp;
+ field public CharSequence venueName;
+ }
+
+ public static class ScanResult.InformationElement {
+ ctor public ScanResult.InformationElement(@NonNull android.net.wifi.ScanResult.InformationElement);
+ method @NonNull public java.nio.ByteBuffer getBytes();
+ method public int getId();
+ method public int getIdExt();
+ }
+
+ public final class SoftApConfiguration implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public android.net.MacAddress getBssid();
+ method @Nullable public String getPassphrase();
+ method public int getSecurityType();
+ method @Nullable public String getSsid();
+ method public boolean isHiddenSsid();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApConfiguration> CREATOR;
+ field public static final int SECURITY_TYPE_OPEN = 0; // 0x0
+ field public static final int SECURITY_TYPE_WPA2_PSK = 1; // 0x1
+ field public static final int SECURITY_TYPE_WPA3_SAE = 3; // 0x3
+ field public static final int SECURITY_TYPE_WPA3_SAE_TRANSITION = 2; // 0x2
+ }
+
+ public enum SupplicantState implements android.os.Parcelable {
+ method public int describeContents();
+ method public static boolean isValidState(android.net.wifi.SupplicantState);
+ method public void writeToParcel(android.os.Parcel, int);
+ enum_constant public static final android.net.wifi.SupplicantState ASSOCIATED;
+ enum_constant public static final android.net.wifi.SupplicantState ASSOCIATING;
+ enum_constant public static final android.net.wifi.SupplicantState AUTHENTICATING;
+ enum_constant public static final android.net.wifi.SupplicantState COMPLETED;
+ enum_constant public static final android.net.wifi.SupplicantState DISCONNECTED;
+ enum_constant public static final android.net.wifi.SupplicantState DORMANT;
+ enum_constant public static final android.net.wifi.SupplicantState FOUR_WAY_HANDSHAKE;
+ enum_constant public static final android.net.wifi.SupplicantState GROUP_HANDSHAKE;
+ enum_constant public static final android.net.wifi.SupplicantState INACTIVE;
+ enum_constant public static final android.net.wifi.SupplicantState INTERFACE_DISABLED;
+ enum_constant public static final android.net.wifi.SupplicantState INVALID;
+ enum_constant public static final android.net.wifi.SupplicantState SCANNING;
+ enum_constant public static final android.net.wifi.SupplicantState UNINITIALIZED;
+ }
+
+ @Deprecated public class WifiConfiguration implements android.os.Parcelable {
+ ctor @Deprecated public WifiConfiguration();
+ ctor @Deprecated public WifiConfiguration(@NonNull android.net.wifi.WifiConfiguration);
+ method public int describeContents();
+ method @Deprecated public android.net.ProxyInfo getHttpProxy();
+ method @Deprecated @NonNull public String getKey();
+ method @Deprecated @NonNull public android.net.MacAddress getRandomizedMacAddress();
+ method @Deprecated public boolean isPasspoint();
+ method @Deprecated public void setHttpProxy(android.net.ProxyInfo);
+ method @Deprecated public void setSecurityParams(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated public String BSSID;
+ field @Deprecated public String FQDN;
+ field @Deprecated public static final int SECURITY_TYPE_EAP = 3; // 0x3
+ field @Deprecated public static final int SECURITY_TYPE_EAP_SUITE_B = 5; // 0x5
+ field @Deprecated public static final int SECURITY_TYPE_OPEN = 0; // 0x0
+ field @Deprecated public static final int SECURITY_TYPE_OWE = 6; // 0x6
+ field @Deprecated public static final int SECURITY_TYPE_PSK = 2; // 0x2
+ field @Deprecated public static final int SECURITY_TYPE_SAE = 4; // 0x4
+ field @Deprecated public static final int SECURITY_TYPE_WAPI_CERT = 8; // 0x8
+ field @Deprecated public static final int SECURITY_TYPE_WAPI_PSK = 7; // 0x7
+ field @Deprecated public static final int SECURITY_TYPE_WEP = 1; // 0x1
+ field @Deprecated public String SSID;
+ field @Deprecated @NonNull public java.util.BitSet allowedAuthAlgorithms;
+ field @Deprecated @NonNull public java.util.BitSet allowedGroupCiphers;
+ field @Deprecated @NonNull public java.util.BitSet allowedGroupManagementCiphers;
+ field @Deprecated @NonNull public java.util.BitSet allowedKeyManagement;
+ field @Deprecated @NonNull public java.util.BitSet allowedPairwiseCiphers;
+ field @Deprecated @NonNull public java.util.BitSet allowedProtocols;
+ field @Deprecated @NonNull public java.util.BitSet allowedSuiteBCiphers;
+ field @Deprecated public android.net.wifi.WifiEnterpriseConfig enterpriseConfig;
+ field @Deprecated public boolean hiddenSSID;
+ field @Deprecated public boolean isHomeProviderNetwork;
+ field @Deprecated public int networkId;
+ field @Deprecated public String preSharedKey;
+ field @Deprecated public int priority;
+ field @Deprecated public String providerFriendlyName;
+ field @Deprecated public long[] roamingConsortiumIds;
+ field @Deprecated public int status;
+ field @Deprecated public String[] wepKeys;
+ field @Deprecated public int wepTxKeyIndex;
+ }
+
+ @Deprecated public static class WifiConfiguration.AuthAlgorithm {
+ field @Deprecated public static final int LEAP = 2; // 0x2
+ field @Deprecated public static final int OPEN = 0; // 0x0
+ field @Deprecated public static final int SAE = 3; // 0x3
+ field @Deprecated public static final int SHARED = 1; // 0x1
+ field @Deprecated public static final String[] strings;
+ field @Deprecated public static final String varName = "auth_alg";
+ }
+
+ @Deprecated public static class WifiConfiguration.GroupCipher {
+ field @Deprecated public static final int CCMP = 3; // 0x3
+ field @Deprecated public static final int GCMP_256 = 5; // 0x5
+ field @Deprecated public static final int SMS4 = 6; // 0x6
+ field @Deprecated public static final int TKIP = 2; // 0x2
+ field @Deprecated public static final int WEP104 = 1; // 0x1
+ field @Deprecated public static final int WEP40 = 0; // 0x0
+ field @Deprecated public static final String[] strings;
+ field @Deprecated public static final String varName = "group";
+ }
+
+ @Deprecated public static class WifiConfiguration.GroupMgmtCipher {
+ field @Deprecated public static final int BIP_CMAC_256 = 0; // 0x0
+ field @Deprecated public static final int BIP_GMAC_128 = 1; // 0x1
+ field @Deprecated public static final int BIP_GMAC_256 = 2; // 0x2
+ }
+
+ @Deprecated public static class WifiConfiguration.KeyMgmt {
+ field @Deprecated public static final int IEEE8021X = 3; // 0x3
+ field @Deprecated public static final int NONE = 0; // 0x0
+ field @Deprecated public static final int OWE = 9; // 0x9
+ field @Deprecated public static final int SAE = 8; // 0x8
+ field @Deprecated public static final int SUITE_B_192 = 10; // 0xa
+ field @Deprecated public static final int WPA_EAP = 2; // 0x2
+ field @Deprecated public static final int WPA_PSK = 1; // 0x1
+ field @Deprecated public static final String[] strings;
+ field @Deprecated public static final String varName = "key_mgmt";
+ }
+
+ @Deprecated public static class WifiConfiguration.PairwiseCipher {
+ field @Deprecated public static final int CCMP = 2; // 0x2
+ field @Deprecated public static final int GCMP_256 = 3; // 0x3
+ field @Deprecated public static final int NONE = 0; // 0x0
+ field @Deprecated public static final int SMS4 = 4; // 0x4
+ field @Deprecated public static final int TKIP = 1; // 0x1
+ field @Deprecated public static final String[] strings;
+ field @Deprecated public static final String varName = "pairwise";
+ }
+
+ @Deprecated public static class WifiConfiguration.Protocol {
+ field @Deprecated public static final int RSN = 1; // 0x1
+ field @Deprecated public static final int WAPI = 3; // 0x3
+ field @Deprecated public static final int WPA = 0; // 0x0
+ field @Deprecated public static final String[] strings;
+ field @Deprecated public static final String varName = "proto";
+ }
+
+ @Deprecated public static class WifiConfiguration.Status {
+ field @Deprecated public static final int CURRENT = 0; // 0x0
+ field @Deprecated public static final int DISABLED = 1; // 0x1
+ field @Deprecated public static final int ENABLED = 2; // 0x2
+ field @Deprecated public static final String[] strings;
+ }
+
+ public class WifiEnterpriseConfig implements android.os.Parcelable {
+ ctor public WifiEnterpriseConfig();
+ ctor public WifiEnterpriseConfig(android.net.wifi.WifiEnterpriseConfig);
+ method public int describeContents();
+ method public String getAltSubjectMatch();
+ method public String getAnonymousIdentity();
+ method @Nullable public java.security.cert.X509Certificate getCaCertificate();
+ 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();
+ method public String getPassword();
+ method public int getPhase2Method();
+ method public String getPlmn();
+ method public String getRealm();
+ method @Deprecated public String getSubjectMatch();
+ method public boolean isAuthenticationSimBased();
+ method public void setAltSubjectMatch(String);
+ method public void setAnonymousIdentity(String);
+ method public void setCaCertificate(@Nullable java.security.cert.X509Certificate);
+ method public void setCaCertificates(@Nullable java.security.cert.X509Certificate[]);
+ method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
+ method public void setClientKeyEntryWithCertificateChain(java.security.PrivateKey, java.security.cert.X509Certificate[]);
+ method public void setDomainSuffixMatch(String);
+ method public void setEapMethod(int);
+ method public void setIdentity(String);
+ method public void setPassword(String);
+ method public void setPhase2Method(int);
+ method public void setPlmn(String);
+ method public void setRealm(String);
+ method @Deprecated public void setSubjectMatch(String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiEnterpriseConfig> CREATOR;
+ field public static final String EXTRA_WAPI_AS_CERTIFICATE_DATA = "android.net.wifi.extra.WAPI_AS_CERTIFICATE_DATA";
+ field public static final String EXTRA_WAPI_AS_CERTIFICATE_NAME = "android.net.wifi.extra.WAPI_AS_CERTIFICATE_NAME";
+ field public static final String EXTRA_WAPI_USER_CERTIFICATE_DATA = "android.net.wifi.extra.WAPI_USER_CERTIFICATE_DATA";
+ field public static final String EXTRA_WAPI_USER_CERTIFICATE_NAME = "android.net.wifi.extra.WAPI_USER_CERTIFICATE_NAME";
+ field public static final String WAPI_AS_CERTIFICATE = "WAPIAS_";
+ field public static final String WAPI_USER_CERTIFICATE = "WAPIUSR_";
+ }
+
+ public static final class WifiEnterpriseConfig.Eap {
+ field public static final int AKA = 5; // 0x5
+ field public static final int AKA_PRIME = 6; // 0x6
+ field public static final int NONE = -1; // 0xffffffff
+ field public static final int PEAP = 0; // 0x0
+ field public static final int PWD = 3; // 0x3
+ field public static final int SIM = 4; // 0x4
+ field public static final int TLS = 1; // 0x1
+ field public static final int TTLS = 2; // 0x2
+ field public static final int UNAUTH_TLS = 7; // 0x7
+ field public static final int WAPI_CERT = 8; // 0x8
+ }
+
+ public static final class WifiEnterpriseConfig.Phase2 {
+ field public static final int AKA = 6; // 0x6
+ field public static final int AKA_PRIME = 7; // 0x7
+ field public static final int GTC = 4; // 0x4
+ field public static final int MSCHAP = 2; // 0x2
+ field public static final int MSCHAPV2 = 3; // 0x3
+ field public static final int NONE = 0; // 0x0
+ field public static final int PAP = 1; // 0x1
+ field public static final int SIM = 5; // 0x5
+ }
+
+ public class WifiInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public String getBSSID();
+ method public static android.net.NetworkInfo.DetailedState getDetailedStateOf(android.net.wifi.SupplicantState);
+ method public int getFrequency();
+ method public boolean getHiddenSSID();
+ method public int getIpAddress();
+ method public int getLinkSpeed();
+ method public String getMacAddress();
+ method public int getMaxSupportedRxLinkSpeedMbps();
+ method public int getMaxSupportedTxLinkSpeedMbps();
+ method public int getNetworkId();
+ method @Nullable public String getPasspointFqdn();
+ method @Nullable public String getPasspointProviderFriendlyName();
+ method public int getRssi();
+ method @IntRange(from=0xffffffff) public int getRxLinkSpeedMbps();
+ method public String getSSID();
+ method public android.net.wifi.SupplicantState getSupplicantState();
+ method @IntRange(from=0xffffffff) public int getTxLinkSpeedMbps();
+ method public int getWifiStandard();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final String FREQUENCY_UNITS = "MHz";
+ field public static final String LINK_SPEED_UNITS = "Mbps";
+ field public static final int LINK_SPEED_UNKNOWN = -1; // 0xffffffff
+ }
+
+ 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 @Deprecated public int addNetwork(android.net.wifi.WifiConfiguration);
+ method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int addNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
+ method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
+ method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public void addSuggestionConnectionStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SuggestionConnectionStatusListener);
+ method @Deprecated public static int calculateSignalLevel(int, int);
+ method @IntRange(from=0) public int calculateSignalLevel(int);
+ method @Deprecated public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
+ method public static int compareSignalLevel(int, int);
+ method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(String);
+ method public android.net.wifi.WifiManager.WifiLock createWifiLock(int, String);
+ method @Deprecated public android.net.wifi.WifiManager.WifiLock createWifiLock(String);
+ method @Deprecated public boolean disableNetwork(int);
+ method @Deprecated public boolean disconnect();
+ method @Deprecated public boolean enableNetwork(int, boolean);
+ method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks();
+ method public android.net.wifi.WifiInfo getConnectionInfo();
+ method public android.net.DhcpInfo getDhcpInfo();
+ method public int getMaxNumberOfNetworkSuggestionsPerApp();
+ method @IntRange(from=0) public int getMaxSignalLevel();
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public java.util.List<android.net.wifi.WifiNetworkSuggestion> getNetworkSuggestions();
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
+ method public java.util.List<android.net.wifi.ScanResult> getScanResults();
+ method public int getWifiState();
+ method public boolean is5GHzBandSupported();
+ method public boolean is6GHzBandSupported();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isAutoWakeupEnabled();
+ method @Deprecated public boolean isDeviceToApRttSupported();
+ method public boolean isEasyConnectSupported();
+ method public boolean isEnhancedOpenSupported();
+ method public boolean isEnhancedPowerReportingSupported();
+ method public boolean isP2pSupported();
+ method public boolean isPreferredNetworkOffloadSupported();
+ method @Deprecated public boolean isScanAlwaysAvailable();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isScanThrottleEnabled();
+ method public boolean isStaApConcurrencySupported();
+ method public boolean isTdlsSupported();
+ method public boolean isWapiSupported();
+ method public boolean isWifiEnabled();
+ method public boolean isWifiStandardSupported(int);
+ method public boolean isWpa3SaeSupported();
+ method public boolean isWpa3SuiteBSupported();
+ method @Deprecated public boolean pingSupplicant();
+ method @Deprecated public boolean reassociate();
+ method @Deprecated public boolean reconnect();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void registerScanResultsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.ScanResultsCallback);
+ method @Deprecated public boolean removeNetwork(int);
+ method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int removeNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_CARRIER_PROVISIONING}) public void removePasspointConfiguration(String);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void removeSuggestionConnectionStatusListener(@NonNull android.net.wifi.WifiManager.SuggestionConnectionStatusListener);
+ method @Deprecated public boolean saveConfiguration();
+ method public void setTdlsEnabled(java.net.InetAddress, boolean);
+ method public void setTdlsEnabledWithMacAddress(String, boolean);
+ method @Deprecated public boolean setWifiEnabled(boolean);
+ method @RequiresPermission(allOf={android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void startLocalOnlyHotspot(android.net.wifi.WifiManager.LocalOnlyHotspotCallback, @Nullable android.os.Handler);
+ method @Deprecated public boolean startScan();
+ method @Deprecated public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void unregisterScanResultsCallback(@NonNull android.net.wifi.WifiManager.ScanResultsCallback);
+ method @Deprecated public int updateNetwork(android.net.wifi.WifiConfiguration);
+ field public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
+ field public static final String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
+ field public static final String ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION = "android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION";
+ field public static final String ACTION_WIFI_SCAN_AVAILABILITY_CHANGED = "android.net.wifi.action.WIFI_SCAN_AVAILABILITY_CHANGED";
+ field @Deprecated public static final int ERROR_AUTHENTICATING = 1; // 0x1
+ field @Deprecated public static final String EXTRA_BSSID = "bssid";
+ field public static final String EXTRA_NETWORK_INFO = "networkInfo";
+ field public static final String EXTRA_NETWORK_SUGGESTION = "android.net.wifi.extra.NETWORK_SUGGESTION";
+ field public static final String EXTRA_NEW_RSSI = "newRssi";
+ field @Deprecated public static final String EXTRA_NEW_STATE = "newState";
+ field public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
+ field public static final String EXTRA_RESULTS_UPDATED = "resultsUpdated";
+ field public static final String EXTRA_SCAN_AVAILABLE = "android.net.wifi.extra.SCAN_AVAILABLE";
+ field @Deprecated public static final String EXTRA_SUPPLICANT_CONNECTED = "connected";
+ field @Deprecated public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError";
+ field @Deprecated public static final String EXTRA_WIFI_INFO = "wifiInfo";
+ field public static final String EXTRA_WIFI_STATE = "wifi_state";
+ field public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
+ field public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
+ field public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED";
+ field public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS";
+ field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE = 3; // 0x3
+ field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP = 4; // 0x4
+ field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_INVALID = 7; // 0x7
+ field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_NOT_ALLOWED = 6; // 0x6
+ field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED = 2; // 0x2
+ field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL = 1; // 0x1
+ field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID = 5; // 0x5
+ field public static final int STATUS_NETWORK_SUGGESTIONS_SUCCESS = 0; // 0x0
+ field public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_ASSOCIATION = 1; // 0x1
+ field public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION = 2; // 0x2
+ field public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_IP_PROVISIONING = 3; // 0x3
+ field public static final int STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN = 0; // 0x0
+ field @Deprecated public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION = "android.net.wifi.supplicant.CONNECTION_CHANGE";
+ field @Deprecated public static final String SUPPLICANT_STATE_CHANGED_ACTION = "android.net.wifi.supplicant.STATE_CHANGE";
+ field public static final String UNKNOWN_SSID = "<unknown ssid>";
+ field @Deprecated public static final int WIFI_MODE_FULL = 1; // 0x1
+ field public static final int WIFI_MODE_FULL_HIGH_PERF = 3; // 0x3
+ field public static final int WIFI_MODE_FULL_LOW_LATENCY = 4; // 0x4
+ field @Deprecated public static final int WIFI_MODE_SCAN_ONLY = 2; // 0x2
+ field public static final String WIFI_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_STATE_CHANGED";
+ field public static final int WIFI_STATE_DISABLED = 1; // 0x1
+ field public static final int WIFI_STATE_DISABLING = 0; // 0x0
+ field public static final int WIFI_STATE_ENABLED = 3; // 0x3
+ field public static final int WIFI_STATE_ENABLING = 2; // 0x2
+ field public static final int WIFI_STATE_UNKNOWN = 4; // 0x4
+ field @Deprecated public static final int WPS_AUTH_FAILURE = 6; // 0x6
+ field @Deprecated public static final int WPS_OVERLAP_ERROR = 3; // 0x3
+ field @Deprecated public static final int WPS_TIMED_OUT = 7; // 0x7
+ field @Deprecated public static final int WPS_TKIP_ONLY_PROHIBITED = 5; // 0x5
+ field @Deprecated public static final int WPS_WEP_PROHIBITED = 4; // 0x4
+ }
+
+ public static class WifiManager.LocalOnlyHotspotCallback {
+ ctor public WifiManager.LocalOnlyHotspotCallback();
+ method public void onFailed(int);
+ method public void onStarted(android.net.wifi.WifiManager.LocalOnlyHotspotReservation);
+ method public void onStopped();
+ field public static final int ERROR_GENERIC = 2; // 0x2
+ field public static final int ERROR_INCOMPATIBLE_MODE = 3; // 0x3
+ field public static final int ERROR_NO_CHANNEL = 1; // 0x1
+ field public static final int ERROR_TETHERING_DISALLOWED = 4; // 0x4
+ }
+
+ public class WifiManager.LocalOnlyHotspotReservation implements java.lang.AutoCloseable {
+ method public void close();
+ method @NonNull public android.net.wifi.SoftApConfiguration getSoftApConfiguration();
+ method @Deprecated @Nullable public android.net.wifi.WifiConfiguration getWifiConfiguration();
+ }
+
+ public class WifiManager.MulticastLock {
+ method public void acquire();
+ method public boolean isHeld();
+ method public void release();
+ method public void setReferenceCounted(boolean);
+ }
+
+ public abstract static class WifiManager.ScanResultsCallback {
+ ctor public WifiManager.ScanResultsCallback();
+ method public abstract void onScanResultsAvailable();
+ }
+
+ public static interface WifiManager.SuggestionConnectionStatusListener {
+ method public void onConnectionStatus(@NonNull android.net.wifi.WifiNetworkSuggestion, int);
+ }
+
+ public class WifiManager.WifiLock {
+ method public void acquire();
+ method public boolean isHeld();
+ method public void release();
+ method public void setReferenceCounted(boolean);
+ method public void setWorkSource(android.os.WorkSource);
+ }
+
+ @Deprecated public abstract static class WifiManager.WpsCallback {
+ ctor @Deprecated public WifiManager.WpsCallback();
+ method @Deprecated public abstract void onFailed(int);
+ method @Deprecated public abstract void onStarted(String);
+ method @Deprecated public abstract void onSucceeded();
+ }
+
+ public final class WifiNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiNetworkSpecifier> CREATOR;
+ }
+
+ public static final class WifiNetworkSpecifier.Builder {
+ ctor public WifiNetworkSpecifier.Builder();
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier build();
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setBssid(@NonNull android.net.MacAddress);
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setBssidPattern(@NonNull android.net.MacAddress, @NonNull android.net.MacAddress);
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setIsEnhancedOpen(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setIsHiddenSsid(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setSsid(@NonNull String);
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setSsidPattern(@NonNull android.os.PatternMatcher);
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setWpa2Passphrase(@NonNull String);
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setWpa3EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+ method @NonNull public android.net.wifi.WifiNetworkSpecifier.Builder setWpa3Passphrase(@NonNull String);
+ }
+
+ public final class WifiNetworkSuggestion implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public android.net.MacAddress getBssid();
+ method @Nullable public android.net.wifi.WifiEnterpriseConfig getEnterpriseConfig();
+ method @Nullable public String getPassphrase();
+ method @Nullable public android.net.wifi.hotspot2.PasspointConfiguration getPasspointConfig();
+ method @IntRange(from=0) public int getPriority();
+ method @Nullable public String getSsid();
+ method public boolean isAppInteractionRequired();
+ method public boolean isCredentialSharedWithUser();
+ method public boolean isEnhancedOpen();
+ method public boolean isHiddenSsid();
+ method public boolean isInitialAutojoinEnabled();
+ method public boolean isMetered();
+ method public boolean isUntrusted();
+ method public boolean isUserInteractionRequired();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiNetworkSuggestion> CREATOR;
+ }
+
+ public static final class WifiNetworkSuggestion.Builder {
+ ctor public WifiNetworkSuggestion.Builder();
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion build();
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setBssid(@NonNull android.net.MacAddress);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setCredentialSharedWithUser(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsAppInteractionRequired(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsEnhancedOpen(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsHiddenSsid(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsInitialAutojoinEnabled(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsMetered(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setIsUserInteractionRequired(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPasspointConfig(@NonNull android.net.wifi.hotspot2.PasspointConfiguration);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setPriority(@IntRange(from=0) int);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setSsid(@NonNull String);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setUntrusted(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWapiEnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWapiPassphrase(@NonNull String);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa2EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa2Passphrase(@NonNull String);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa3EnterpriseConfig(@NonNull android.net.wifi.WifiEnterpriseConfig);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setWpa3Passphrase(@NonNull String);
+ }
+
+ public class WpsInfo implements android.os.Parcelable {
+ ctor public WpsInfo();
+ ctor public WpsInfo(android.net.wifi.WpsInfo);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public String BSSID;
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WpsInfo> CREATOR;
+ field public static final int DISPLAY = 1; // 0x1
+ field public static final int INVALID = 4; // 0x4
+ field public static final int KEYPAD = 2; // 0x2
+ field public static final int LABEL = 3; // 0x3
+ field public static final int PBC = 0; // 0x0
+ field public String pin;
+ field public int setup;
+ }
+
+}
+
+package android.net.wifi.aware {
+
+ public class AttachCallback {
+ ctor public AttachCallback();
+ method public void onAttachFailed();
+ method public void onAttached(android.net.wifi.aware.WifiAwareSession);
+ }
+
+ public final class Characteristics implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getMaxMatchFilterLength();
+ method public int getMaxServiceNameLength();
+ method public int getMaxServiceSpecificInfoLength();
+ method public int getSupportedCipherSuites();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR;
+ field public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_128 = 1; // 0x1
+ field public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_256 = 2; // 0x2
+ }
+
+ public class DiscoverySession implements java.lang.AutoCloseable {
+ method public void close();
+ method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierOpen(@NonNull android.net.wifi.aware.PeerHandle);
+ method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(@NonNull android.net.wifi.aware.PeerHandle, @NonNull String);
+ method public void sendMessage(@NonNull android.net.wifi.aware.PeerHandle, int, @Nullable byte[]);
+ }
+
+ public class DiscoverySessionCallback {
+ ctor public DiscoverySessionCallback();
+ method public void onMessageReceived(android.net.wifi.aware.PeerHandle, byte[]);
+ method public void onMessageSendFailed(int);
+ method public void onMessageSendSucceeded(int);
+ method public void onPublishStarted(@NonNull android.net.wifi.aware.PublishDiscoverySession);
+ method public void onServiceDiscovered(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>);
+ method public void onServiceDiscoveredWithinRange(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>, int);
+ method public void onSessionConfigFailed();
+ method public void onSessionConfigUpdated();
+ method public void onSessionTerminated();
+ method public void onSubscribeStarted(@NonNull android.net.wifi.aware.SubscribeDiscoverySession);
+ }
+
+ public class IdentityChangedListener {
+ ctor public IdentityChangedListener();
+ method public void onIdentityChanged(byte[]);
+ }
+
+ public final class ParcelablePeerHandle extends android.net.wifi.aware.PeerHandle implements android.os.Parcelable {
+ ctor public ParcelablePeerHandle(@NonNull android.net.wifi.aware.PeerHandle);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.ParcelablePeerHandle> CREATOR;
+ }
+
+ public class PeerHandle {
+ }
+
+ public final class PublishConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.PublishConfig> CREATOR;
+ field public static final int PUBLISH_TYPE_SOLICITED = 1; // 0x1
+ field public static final int PUBLISH_TYPE_UNSOLICITED = 0; // 0x0
+ }
+
+ public static final class PublishConfig.Builder {
+ ctor public PublishConfig.Builder();
+ method public android.net.wifi.aware.PublishConfig build();
+ method public android.net.wifi.aware.PublishConfig.Builder setMatchFilter(@Nullable java.util.List<byte[]>);
+ method public android.net.wifi.aware.PublishConfig.Builder setPublishType(int);
+ method public android.net.wifi.aware.PublishConfig.Builder setRangingEnabled(boolean);
+ method public android.net.wifi.aware.PublishConfig.Builder setServiceName(@NonNull String);
+ method public android.net.wifi.aware.PublishConfig.Builder setServiceSpecificInfo(@Nullable byte[]);
+ method public android.net.wifi.aware.PublishConfig.Builder setTerminateNotificationEnabled(boolean);
+ method public android.net.wifi.aware.PublishConfig.Builder setTtlSec(int);
+ }
+
+ public class PublishDiscoverySession extends android.net.wifi.aware.DiscoverySession {
+ method public void updatePublish(@NonNull android.net.wifi.aware.PublishConfig);
+ }
+
+ public final class SubscribeConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.SubscribeConfig> CREATOR;
+ field public static final int SUBSCRIBE_TYPE_ACTIVE = 1; // 0x1
+ field public static final int SUBSCRIBE_TYPE_PASSIVE = 0; // 0x0
+ }
+
+ public static final class SubscribeConfig.Builder {
+ ctor public SubscribeConfig.Builder();
+ method public android.net.wifi.aware.SubscribeConfig build();
+ method public android.net.wifi.aware.SubscribeConfig.Builder setMatchFilter(@Nullable java.util.List<byte[]>);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setMaxDistanceMm(int);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setMinDistanceMm(int);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setServiceName(@NonNull String);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setServiceSpecificInfo(@Nullable byte[]);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setSubscribeType(int);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setTerminateNotificationEnabled(boolean);
+ method public android.net.wifi.aware.SubscribeConfig.Builder setTtlSec(int);
+ }
+
+ public class SubscribeDiscoverySession extends android.net.wifi.aware.DiscoverySession {
+ method public void updateSubscribe(@NonNull android.net.wifi.aware.SubscribeConfig);
+ }
+
+ public class WifiAwareManager {
+ method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @Nullable android.os.Handler);
+ method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @NonNull android.net.wifi.aware.IdentityChangedListener, @Nullable android.os.Handler);
+ method public android.net.wifi.aware.Characteristics getCharacteristics();
+ method public boolean isAvailable();
+ field public static final String ACTION_WIFI_AWARE_STATE_CHANGED = "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED";
+ field public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0; // 0x0
+ field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1
+ }
+
+ public final class WifiAwareNetworkInfo implements android.os.Parcelable android.net.TransportInfo {
+ method public int describeContents();
+ method @Nullable public java.net.Inet6Address getPeerIpv6Addr();
+ method public int getPort();
+ method public int getTransportProtocol();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.WifiAwareNetworkInfo> CREATOR;
+ }
+
+ public final class WifiAwareNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.WifiAwareNetworkSpecifier> CREATOR;
+ }
+
+ public static final class WifiAwareNetworkSpecifier.Builder {
+ ctor public WifiAwareNetworkSpecifier.Builder(@NonNull android.net.wifi.aware.DiscoverySession, @NonNull android.net.wifi.aware.PeerHandle);
+ method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier build();
+ method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPmk(@NonNull byte[]);
+ method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPort(@IntRange(from=0, to=65535) int);
+ method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setPskPassphrase(@NonNull String);
+ method @NonNull public android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder setTransportProtocol(@IntRange(from=0, to=255) int);
+ }
+
+ public class WifiAwareSession implements java.lang.AutoCloseable {
+ method public void close();
+ method public android.net.NetworkSpecifier createNetworkSpecifierOpen(int, @NonNull byte[]);
+ method public android.net.NetworkSpecifier createNetworkSpecifierPassphrase(int, @NonNull byte[], @NonNull String);
+ method public void publish(@NonNull android.net.wifi.aware.PublishConfig, @NonNull android.net.wifi.aware.DiscoverySessionCallback, @Nullable android.os.Handler);
+ method public void subscribe(@NonNull android.net.wifi.aware.SubscribeConfig, @NonNull android.net.wifi.aware.DiscoverySessionCallback, @Nullable android.os.Handler);
+ }
+
+}
+
+package android.net.wifi.hotspot2 {
+
+ public final class ConfigParser {
+ method public static android.net.wifi.hotspot2.PasspointConfiguration parsePasspointConfig(String, byte[]);
+ }
+
+ public final class PasspointConfiguration implements android.os.Parcelable {
+ ctor public PasspointConfiguration();
+ ctor public PasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
+ method public int describeContents();
+ method public android.net.wifi.hotspot2.pps.Credential getCredential();
+ method public android.net.wifi.hotspot2.pps.HomeSp getHomeSp();
+ method public long getSubscriptionExpirationTimeMillis();
+ method @NonNull public String getUniqueId();
+ method public boolean isOsuProvisioned();
+ method public void setCredential(android.net.wifi.hotspot2.pps.Credential);
+ method public void setHomeSp(android.net.wifi.hotspot2.pps.HomeSp);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.PasspointConfiguration> CREATOR;
+ }
+
+}
+
+package android.net.wifi.hotspot2.omadm {
+
+ public final class PpsMoParser {
+ method public static android.net.wifi.hotspot2.PasspointConfiguration parseMoText(String);
+ }
+
+}
+
+package android.net.wifi.hotspot2.pps {
+
+ public final class Credential implements android.os.Parcelable {
+ ctor public Credential();
+ ctor public Credential(android.net.wifi.hotspot2.pps.Credential);
+ method public int describeContents();
+ method public java.security.cert.X509Certificate getCaCertificate();
+ method public android.net.wifi.hotspot2.pps.Credential.CertificateCredential getCertCredential();
+ method public java.security.cert.X509Certificate[] getClientCertificateChain();
+ method public java.security.PrivateKey getClientPrivateKey();
+ method public String getRealm();
+ method public android.net.wifi.hotspot2.pps.Credential.SimCredential getSimCredential();
+ method public android.net.wifi.hotspot2.pps.Credential.UserCredential getUserCredential();
+ method public void setCaCertificate(java.security.cert.X509Certificate);
+ method public void setCertCredential(android.net.wifi.hotspot2.pps.Credential.CertificateCredential);
+ method public void setClientCertificateChain(java.security.cert.X509Certificate[]);
+ method public void setClientPrivateKey(java.security.PrivateKey);
+ method public void setRealm(String);
+ method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
+ method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential> CREATOR;
+ }
+
+ public static final class Credential.CertificateCredential implements android.os.Parcelable {
+ ctor public Credential.CertificateCredential();
+ ctor public Credential.CertificateCredential(android.net.wifi.hotspot2.pps.Credential.CertificateCredential);
+ method public int describeContents();
+ method public byte[] getCertSha256Fingerprint();
+ method public String getCertType();
+ method public void setCertSha256Fingerprint(byte[]);
+ method public void setCertType(String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.CertificateCredential> CREATOR;
+ }
+
+ public static final class Credential.SimCredential implements android.os.Parcelable {
+ ctor public Credential.SimCredential();
+ ctor public Credential.SimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
+ method public int describeContents();
+ method public int getEapType();
+ method public String getImsi();
+ method public void setEapType(int);
+ method public void setImsi(String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.SimCredential> CREATOR;
+ }
+
+ public static final class Credential.UserCredential implements android.os.Parcelable {
+ ctor public Credential.UserCredential();
+ ctor public Credential.UserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
+ method public int describeContents();
+ method public int getEapType();
+ method public String getNonEapInnerMethod();
+ method public String getPassword();
+ method public String getUsername();
+ method public void setEapType(int);
+ method public void setNonEapInnerMethod(String);
+ method public void setPassword(String);
+ method public void setUsername(String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.UserCredential> CREATOR;
+ }
+
+ public final class HomeSp implements android.os.Parcelable {
+ ctor public HomeSp();
+ ctor public HomeSp(android.net.wifi.hotspot2.pps.HomeSp);
+ method public int describeContents();
+ method public String getFqdn();
+ method public String getFriendlyName();
+ method public long[] getRoamingConsortiumOis();
+ method public void setFqdn(String);
+ method public void setFriendlyName(String);
+ method public void setRoamingConsortiumOis(long[]);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
+ }
+
+}
+
+package android.net.wifi.p2p {
+
+ public class WifiP2pConfig implements android.os.Parcelable {
+ ctor public WifiP2pConfig();
+ ctor public WifiP2pConfig(android.net.wifi.p2p.WifiP2pConfig);
+ method public int describeContents();
+ method public int getGroupOwnerBand();
+ method public int getNetworkId();
+ method @Nullable public String getNetworkName();
+ method @Nullable public String getPassphrase();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pConfig> CREATOR;
+ field public static final int GROUP_OWNER_BAND_2GHZ = 1; // 0x1
+ field public static final int GROUP_OWNER_BAND_5GHZ = 2; // 0x2
+ field public static final int GROUP_OWNER_BAND_AUTO = 0; // 0x0
+ field public static final int GROUP_OWNER_INTENT_AUTO = -1; // 0xffffffff
+ field public static final int GROUP_OWNER_INTENT_MAX = 15; // 0xf
+ field public static final int GROUP_OWNER_INTENT_MIN = 0; // 0x0
+ field public String deviceAddress;
+ field @IntRange(from=0, to=15) public int groupOwnerIntent;
+ field public android.net.wifi.WpsInfo wps;
+ }
+
+ public static final class WifiP2pConfig.Builder {
+ ctor public WifiP2pConfig.Builder();
+ method @NonNull public android.net.wifi.p2p.WifiP2pConfig build();
+ method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder enablePersistentMode(boolean);
+ method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setDeviceAddress(@Nullable android.net.MacAddress);
+ method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupOperatingBand(int);
+ method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupOperatingFrequency(int);
+ method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setNetworkName(@NonNull String);
+ method @NonNull public android.net.wifi.p2p.WifiP2pConfig.Builder setPassphrase(@NonNull String);
+ }
+
+ public class WifiP2pDevice implements android.os.Parcelable {
+ ctor public WifiP2pDevice();
+ ctor public WifiP2pDevice(android.net.wifi.p2p.WifiP2pDevice);
+ method public int describeContents();
+ method @Nullable public android.net.wifi.p2p.WifiP2pWfdInfo getWfdInfo();
+ method public boolean isGroupOwner();
+ method public boolean isServiceDiscoveryCapable();
+ method public void update(@NonNull android.net.wifi.p2p.WifiP2pDevice);
+ method public boolean wpsDisplaySupported();
+ method public boolean wpsKeypadSupported();
+ method public boolean wpsPbcSupported();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int AVAILABLE = 3; // 0x3
+ field public static final int CONNECTED = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pDevice> CREATOR;
+ field public static final int FAILED = 2; // 0x2
+ field public static final int INVITED = 1; // 0x1
+ field public static final int UNAVAILABLE = 4; // 0x4
+ field public String deviceAddress;
+ field public String deviceName;
+ field public String primaryDeviceType;
+ field public String secondaryDeviceType;
+ field public int status;
+ }
+
+ public class WifiP2pDeviceList implements android.os.Parcelable {
+ ctor public WifiP2pDeviceList();
+ ctor public WifiP2pDeviceList(android.net.wifi.p2p.WifiP2pDeviceList);
+ method public int describeContents();
+ method public android.net.wifi.p2p.WifiP2pDevice get(String);
+ method public java.util.Collection<android.net.wifi.p2p.WifiP2pDevice> getDeviceList();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pDeviceList> CREATOR;
+ }
+
+ public class WifiP2pGroup implements android.os.Parcelable {
+ ctor public WifiP2pGroup();
+ ctor public WifiP2pGroup(android.net.wifi.p2p.WifiP2pGroup);
+ method public int describeContents();
+ method public java.util.Collection<android.net.wifi.p2p.WifiP2pDevice> getClientList();
+ method public int getFrequency();
+ method public String getInterface();
+ method public int getNetworkId();
+ method public String getNetworkName();
+ method public android.net.wifi.p2p.WifiP2pDevice getOwner();
+ method public String getPassphrase();
+ method public boolean isGroupOwner();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pGroup> CREATOR;
+ field public static final int NETWORK_ID_PERSISTENT = -2; // 0xfffffffe
+ field public static final int NETWORK_ID_TEMPORARY = -1; // 0xffffffff
+ }
+
+ public class WifiP2pInfo implements android.os.Parcelable {
+ ctor public WifiP2pInfo();
+ ctor public WifiP2pInfo(android.net.wifi.p2p.WifiP2pInfo);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pInfo> CREATOR;
+ field public boolean groupFormed;
+ field public java.net.InetAddress groupOwnerAddress;
+ field public boolean isGroupOwner;
+ }
+
+ public class WifiP2pManager {
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void addLocalService(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceInfo, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method public void addServiceRequest(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceRequest, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method public void cancelConnect(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method public void clearLocalServices(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method public void clearServiceRequests(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void connect(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pConfig, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void createGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void createGroup(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pConfig, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void discoverPeers(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void discoverServices(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method public android.net.wifi.p2p.WifiP2pManager.Channel initialize(android.content.Context, android.os.Looper, android.net.wifi.p2p.WifiP2pManager.ChannelListener);
+ method public void removeGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method public void removeLocalService(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceInfo, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method public void removeServiceRequest(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.nsd.WifiP2pServiceRequest, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method public void requestConnectionInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ConnectionInfoListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestDeviceInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pManager.DeviceInfoListener);
+ method public void requestDiscoveryState(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pManager.DiscoveryStateListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestGroupInfo(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.GroupInfoListener);
+ method public void requestNetworkInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pManager.NetworkInfoListener);
+ method public void requestP2pState(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pManager.P2pStateListener);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestPeers(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.PeerListListener);
+ method public void setDnsSdResponseListeners(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.DnsSdServiceResponseListener, android.net.wifi.p2p.WifiP2pManager.DnsSdTxtRecordListener);
+ method public void setServiceResponseListener(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ServiceResponseListener);
+ method public void setUpnpServiceResponseListener(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.UpnpServiceResponseListener);
+ method public void stopPeerDiscovery(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ field public static final int BUSY = 2; // 0x2
+ field public static final int ERROR = 0; // 0x0
+ field public static final String EXTRA_DISCOVERY_STATE = "discoveryState";
+ field public static final String EXTRA_NETWORK_INFO = "networkInfo";
+ field public static final String EXTRA_P2P_DEVICE_LIST = "wifiP2pDeviceList";
+ field public static final String EXTRA_WIFI_P2P_DEVICE = "wifiP2pDevice";
+ field public static final String EXTRA_WIFI_P2P_GROUP = "p2pGroupInfo";
+ field public static final String EXTRA_WIFI_P2P_INFO = "wifiP2pInfo";
+ field public static final String EXTRA_WIFI_STATE = "wifi_p2p_state";
+ field public static final int NO_SERVICE_REQUESTS = 3; // 0x3
+ field public static final int P2P_UNSUPPORTED = 1; // 0x1
+ field public static final String WIFI_P2P_CONNECTION_CHANGED_ACTION = "android.net.wifi.p2p.CONNECTION_STATE_CHANGE";
+ field public static final String WIFI_P2P_DISCOVERY_CHANGED_ACTION = "android.net.wifi.p2p.DISCOVERY_STATE_CHANGE";
+ field public static final int WIFI_P2P_DISCOVERY_STARTED = 2; // 0x2
+ field public static final int WIFI_P2P_DISCOVERY_STOPPED = 1; // 0x1
+ field public static final String WIFI_P2P_PEERS_CHANGED_ACTION = "android.net.wifi.p2p.PEERS_CHANGED";
+ field public static final String WIFI_P2P_STATE_CHANGED_ACTION = "android.net.wifi.p2p.STATE_CHANGED";
+ field public static final int WIFI_P2P_STATE_DISABLED = 1; // 0x1
+ field public static final int WIFI_P2P_STATE_ENABLED = 2; // 0x2
+ field public static final String WIFI_P2P_THIS_DEVICE_CHANGED_ACTION = "android.net.wifi.p2p.THIS_DEVICE_CHANGED";
+ }
+
+ public static interface WifiP2pManager.ActionListener {
+ method public void onFailure(int);
+ method public void onSuccess();
+ }
+
+ public static class WifiP2pManager.Channel implements java.lang.AutoCloseable {
+ method public void close();
+ }
+
+ public static interface WifiP2pManager.ChannelListener {
+ method public void onChannelDisconnected();
+ }
+
+ public static interface WifiP2pManager.ConnectionInfoListener {
+ method public void onConnectionInfoAvailable(android.net.wifi.p2p.WifiP2pInfo);
+ }
+
+ public static interface WifiP2pManager.DeviceInfoListener {
+ method public void onDeviceInfoAvailable(@Nullable android.net.wifi.p2p.WifiP2pDevice);
+ }
+
+ public static interface WifiP2pManager.DiscoveryStateListener {
+ method public void onDiscoveryStateAvailable(int);
+ }
+
+ public static interface WifiP2pManager.DnsSdServiceResponseListener {
+ method public void onDnsSdServiceAvailable(String, String, android.net.wifi.p2p.WifiP2pDevice);
+ }
+
+ public static interface WifiP2pManager.DnsSdTxtRecordListener {
+ method public void onDnsSdTxtRecordAvailable(String, java.util.Map<java.lang.String,java.lang.String>, android.net.wifi.p2p.WifiP2pDevice);
+ }
+
+ public static interface WifiP2pManager.GroupInfoListener {
+ method public void onGroupInfoAvailable(android.net.wifi.p2p.WifiP2pGroup);
+ }
+
+ public static interface WifiP2pManager.NetworkInfoListener {
+ method public void onNetworkInfoAvailable(@NonNull android.net.NetworkInfo);
+ }
+
+ public static interface WifiP2pManager.P2pStateListener {
+ method public void onP2pStateAvailable(int);
+ }
+
+ public static interface WifiP2pManager.PeerListListener {
+ method public void onPeersAvailable(android.net.wifi.p2p.WifiP2pDeviceList);
+ }
+
+ public static interface WifiP2pManager.ServiceResponseListener {
+ method public void onServiceAvailable(int, byte[], android.net.wifi.p2p.WifiP2pDevice);
+ }
+
+ public static interface WifiP2pManager.UpnpServiceResponseListener {
+ method public void onUpnpServiceAvailable(java.util.List<java.lang.String>, android.net.wifi.p2p.WifiP2pDevice);
+ }
+
+ public final class WifiP2pWfdInfo implements android.os.Parcelable {
+ ctor public WifiP2pWfdInfo();
+ ctor public WifiP2pWfdInfo(@Nullable android.net.wifi.p2p.WifiP2pWfdInfo);
+ method public int describeContents();
+ method public int getControlPort();
+ method public int getDeviceType();
+ method public int getMaxThroughput();
+ method public boolean isContentProtectionSupported();
+ method public boolean isEnabled();
+ method public boolean isSessionAvailable();
+ method public void setContentProtectionSupported(boolean);
+ method public void setControlPort(@IntRange(from=0) int);
+ method public boolean setDeviceType(int);
+ method public void setEnabled(boolean);
+ method public void setMaxThroughput(@IntRange(from=0) int);
+ method public void setSessionAvailable(boolean);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pWfdInfo> CREATOR;
+ field public static final int DEVICE_TYPE_PRIMARY_SINK = 1; // 0x1
+ field public static final int DEVICE_TYPE_SECONDARY_SINK = 2; // 0x2
+ field public static final int DEVICE_TYPE_SOURCE_OR_PRIMARY_SINK = 3; // 0x3
+ field public static final int DEVICE_TYPE_WFD_SOURCE = 0; // 0x0
+ }
+
+}
+
+package android.net.wifi.p2p.nsd {
+
+ public class WifiP2pDnsSdServiceInfo extends android.net.wifi.p2p.nsd.WifiP2pServiceInfo {
+ method public static android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceInfo newInstance(String, String, java.util.Map<java.lang.String,java.lang.String>);
+ }
+
+ public class WifiP2pDnsSdServiceRequest extends android.net.wifi.p2p.nsd.WifiP2pServiceRequest {
+ method public static android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest newInstance();
+ method public static android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest newInstance(String);
+ method public static android.net.wifi.p2p.nsd.WifiP2pDnsSdServiceRequest newInstance(String, String);
+ }
+
+ public class WifiP2pServiceInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int SERVICE_TYPE_ALL = 0; // 0x0
+ field public static final int SERVICE_TYPE_BONJOUR = 1; // 0x1
+ field public static final int SERVICE_TYPE_UPNP = 2; // 0x2
+ field public static final int SERVICE_TYPE_VENDOR_SPECIFIC = 255; // 0xff
+ }
+
+ public class WifiP2pServiceRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public static android.net.wifi.p2p.nsd.WifiP2pServiceRequest newInstance(int, String);
+ method public static android.net.wifi.p2p.nsd.WifiP2pServiceRequest newInstance(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ }
+
+ public class WifiP2pUpnpServiceInfo extends android.net.wifi.p2p.nsd.WifiP2pServiceInfo {
+ method public static android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo newInstance(String, String, java.util.List<java.lang.String>);
+ }
+
+ public class WifiP2pUpnpServiceRequest extends android.net.wifi.p2p.nsd.WifiP2pServiceRequest {
+ method public static android.net.wifi.p2p.nsd.WifiP2pUpnpServiceRequest newInstance();
+ method public static android.net.wifi.p2p.nsd.WifiP2pUpnpServiceRequest newInstance(String);
+ }
+
+}
+
+package android.net.wifi.rtt {
+
+ public class CivicLocationKeys {
+ field public static final int ADDITIONAL_CODE = 32; // 0x20
+ field public static final int APT = 26; // 0x1a
+ field public static final int BOROUGH = 4; // 0x4
+ field public static final int BRANCH_ROAD_NAME = 36; // 0x24
+ field public static final int BUILDING = 25; // 0x19
+ field public static final int CITY = 3; // 0x3
+ field public static final int COUNTY = 2; // 0x2
+ field public static final int DESK = 33; // 0x21
+ field public static final int FLOOR = 27; // 0x1b
+ field public static final int GROUP_OF_STREETS = 6; // 0x6
+ field public static final int HNO = 19; // 0x13
+ field public static final int HNS = 20; // 0x14
+ field public static final int LANGUAGE = 0; // 0x0
+ field public static final int LMK = 21; // 0x15
+ field public static final int LOC = 22; // 0x16
+ field public static final int NAM = 23; // 0x17
+ field public static final int NEIGHBORHOOD = 5; // 0x5
+ field public static final int PCN = 30; // 0x1e
+ field public static final int POD = 17; // 0x11
+ field public static final int POSTAL_CODE = 24; // 0x18
+ field public static final int PO_BOX = 31; // 0x1f
+ field public static final int PRD = 16; // 0x10
+ field public static final int PRIMARY_ROAD_NAME = 34; // 0x22
+ field public static final int ROAD_SECTION = 35; // 0x23
+ field public static final int ROOM = 28; // 0x1c
+ field public static final int SCRIPT = 128; // 0x80
+ field public static final int STATE = 1; // 0x1
+ field public static final int STREET_NAME_POST_MODIFIER = 39; // 0x27
+ field public static final int STREET_NAME_PRE_MODIFIER = 38; // 0x26
+ field public static final int STS = 18; // 0x12
+ field public static final int SUBBRANCH_ROAD_NAME = 37; // 0x25
+ field public static final int TYPE_OF_PLACE = 29; // 0x1d
+ }
+
+ public final class RangingRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public static int getMaxPeers();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.RangingRequest> CREATOR;
+ }
+
+ public static final class RangingRequest.Builder {
+ ctor public RangingRequest.Builder();
+ method public android.net.wifi.rtt.RangingRequest.Builder addAccessPoint(@NonNull android.net.wifi.ScanResult);
+ method public android.net.wifi.rtt.RangingRequest.Builder addAccessPoints(@NonNull java.util.List<android.net.wifi.ScanResult>);
+ method public android.net.wifi.rtt.RangingRequest.Builder addWifiAwarePeer(@NonNull android.net.MacAddress);
+ method public android.net.wifi.rtt.RangingRequest.Builder addWifiAwarePeer(@NonNull android.net.wifi.aware.PeerHandle);
+ method public android.net.wifi.rtt.RangingRequest build();
+ }
+
+ public final class RangingResult implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getDistanceMm();
+ method public int getDistanceStdDevMm();
+ method @Nullable public android.net.MacAddress getMacAddress();
+ method public int getNumAttemptedMeasurements();
+ method public int getNumSuccessfulMeasurements();
+ method @Nullable public android.net.wifi.aware.PeerHandle getPeerHandle();
+ method public long getRangingTimestampMillis();
+ method public int getRssi();
+ method public int getStatus();
+ method @Nullable public android.net.wifi.rtt.ResponderLocation getUnverifiedResponderLocation();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.RangingResult> CREATOR;
+ field public static final int STATUS_FAIL = 1; // 0x1
+ field public static final int STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC = 2; // 0x2
+ field public static final int STATUS_SUCCESS = 0; // 0x0
+ }
+
+ public abstract class RangingResultCallback {
+ ctor public RangingResultCallback();
+ method public abstract void onRangingFailure(int);
+ method public abstract void onRangingResults(@NonNull java.util.List<android.net.wifi.rtt.RangingResult>);
+ field public static final int STATUS_CODE_FAIL = 1; // 0x1
+ field public static final int STATUS_CODE_FAIL_RTT_NOT_AVAILABLE = 2; // 0x2
+ }
+
+ public final class ResponderLocation implements android.os.Parcelable {
+ method public int describeContents();
+ method public double getAltitude();
+ method public int getAltitudeType();
+ method public double getAltitudeUncertainty();
+ method public java.util.List<android.net.MacAddress> getColocatedBssids();
+ method public int getDatum();
+ method public int getExpectedToMove();
+ method public double getFloorNumber();
+ method public double getHeightAboveFloorMeters();
+ method public double getHeightAboveFloorUncertaintyMeters();
+ method public double getLatitude();
+ method public double getLatitudeUncertainty();
+ method public int getLciVersion();
+ method public double getLongitude();
+ method public double getLongitudeUncertainty();
+ method @Nullable public String getMapImageMimeType();
+ method @Nullable public android.net.Uri getMapImageUri();
+ method public boolean getRegisteredLocationAgreementIndication();
+ method public boolean isLciSubelementValid();
+ method public boolean isZaxisSubelementValid();
+ method @Nullable public android.location.Address toCivicLocationAddress();
+ method @Nullable public android.util.SparseArray<java.lang.String> toCivicLocationSparseArray();
+ method @NonNull public android.location.Location toLocation();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int ALTITUDE_FLOORS = 2; // 0x2
+ field public static final int ALTITUDE_METERS = 1; // 0x1
+ field public static final int ALTITUDE_UNDEFINED = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.ResponderLocation> CREATOR;
+ field public static final int DATUM_NAD83_MLLW = 3; // 0x3
+ field public static final int DATUM_NAD83_NAV88 = 2; // 0x2
+ field public static final int DATUM_UNDEFINED = 0; // 0x0
+ field public static final int DATUM_WGS84 = 1; // 0x1
+ field public static final int LCI_VERSION_1 = 1; // 0x1
+ field public static final int LOCATION_FIXED = 0; // 0x0
+ field public static final int LOCATION_MOVEMENT_UNKNOWN = 2; // 0x2
+ field public static final int LOCATION_RESERVED = 3; // 0x3
+ field public static final int LOCATION_VARIABLE = 1; // 0x1
+ }
+
+ public class WifiRttManager {
+ method public boolean isAvailable();
+ method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.ACCESS_WIFI_STATE}) public void startRanging(@NonNull android.net.wifi.rtt.RangingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.rtt.RangingResultCallback);
+ field public static final String ACTION_WIFI_RTT_STATE_CHANGED = "android.net.wifi.rtt.action.WIFI_RTT_STATE_CHANGED";
+ }
+
+}
+
diff --git a/wifi/api/module-lib-current.txt b/wifi/api/module-lib-current.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/wifi/api/module-lib-current.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/wifi/api/module-lib-removed.txt b/wifi/api/module-lib-removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/wifi/api/module-lib-removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/wifi/api/removed.txt b/wifi/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/wifi/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
new file mode 100644
index 0000000..150a650
--- /dev/null
+++ b/wifi/api/system-current.txt
@@ -0,0 +1,939 @@
+// Signature format: 2.0
+package android.net.wifi {
+
+ public abstract class EasyConnectStatusCallback {
+ ctor public EasyConnectStatusCallback();
+ method public abstract void onConfiguratorSuccess(int);
+ method public abstract void onEnrolleeSuccess(int);
+ method public void onFailure(int);
+ method public void onFailure(int, @Nullable String, @NonNull android.util.SparseArray<int[]>, @NonNull int[]);
+ method public abstract void onProgress(int);
+ field public static final int EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS = 0; // 0x0
+ field public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED = 3; // 0x3
+ field public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE = 2; // 0x2
+ field public static final int EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING = 1; // 0x1
+ field public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED = 1; // 0x1
+ field public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT = 0; // 0x0
+ }
+
+ @Deprecated public class RttManager {
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void disableResponder(android.net.wifi.RttManager.ResponderCallback);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void enableResponder(android.net.wifi.RttManager.ResponderCallback);
+ method @Deprecated public android.net.wifi.RttManager.Capabilities getCapabilities();
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.net.wifi.RttManager.RttCapabilities getRttCapabilities();
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startRanging(android.net.wifi.RttManager.RttParams[], android.net.wifi.RttManager.RttListener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void stopRanging(android.net.wifi.RttManager.RttListener);
+ field @Deprecated public static final int BASE;
+ field @Deprecated public static final int CMD_OP_ABORTED;
+ field @Deprecated public static final int CMD_OP_DISABLE_RESPONDER;
+ field @Deprecated public static final int CMD_OP_ENABLE_RESPONDER;
+ field @Deprecated public static final int CMD_OP_ENALBE_RESPONDER_FAILED;
+ field @Deprecated public static final int CMD_OP_ENALBE_RESPONDER_SUCCEEDED;
+ field @Deprecated public static final int CMD_OP_FAILED;
+ field @Deprecated public static final int CMD_OP_START_RANGING;
+ field @Deprecated public static final int CMD_OP_STOP_RANGING;
+ field @Deprecated public static final int CMD_OP_SUCCEEDED;
+ field @Deprecated public static final String DESCRIPTION_KEY = "android.net.wifi.RttManager.Description";
+ field @Deprecated public static final int PREAMBLE_HT = 2; // 0x2
+ field @Deprecated public static final int PREAMBLE_LEGACY = 1; // 0x1
+ field @Deprecated public static final int PREAMBLE_VHT = 4; // 0x4
+ field @Deprecated public static final int REASON_INITIATOR_NOT_ALLOWED_WHEN_RESPONDER_ON = -6; // 0xfffffffa
+ field @Deprecated public static final int REASON_INVALID_LISTENER = -3; // 0xfffffffd
+ field @Deprecated public static final int REASON_INVALID_REQUEST = -4; // 0xfffffffc
+ field @Deprecated public static final int REASON_NOT_AVAILABLE = -2; // 0xfffffffe
+ field @Deprecated public static final int REASON_PERMISSION_DENIED = -5; // 0xfffffffb
+ field @Deprecated public static final int REASON_UNSPECIFIED = -1; // 0xffffffff
+ field @Deprecated public static final int RTT_BW_10_SUPPORT = 2; // 0x2
+ field @Deprecated public static final int RTT_BW_160_SUPPORT = 32; // 0x20
+ field @Deprecated public static final int RTT_BW_20_SUPPORT = 4; // 0x4
+ field @Deprecated public static final int RTT_BW_40_SUPPORT = 8; // 0x8
+ field @Deprecated public static final int RTT_BW_5_SUPPORT = 1; // 0x1
+ field @Deprecated public static final int RTT_BW_80_SUPPORT = 16; // 0x10
+ field @Deprecated public static final int RTT_CHANNEL_WIDTH_10 = 6; // 0x6
+ field @Deprecated public static final int RTT_CHANNEL_WIDTH_160 = 3; // 0x3
+ field @Deprecated public static final int RTT_CHANNEL_WIDTH_20 = 0; // 0x0
+ field @Deprecated public static final int RTT_CHANNEL_WIDTH_40 = 1; // 0x1
+ field @Deprecated public static final int RTT_CHANNEL_WIDTH_5 = 5; // 0x5
+ field @Deprecated public static final int RTT_CHANNEL_WIDTH_80 = 2; // 0x2
+ field @Deprecated public static final int RTT_CHANNEL_WIDTH_80P80 = 4; // 0x4
+ field @Deprecated public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1; // 0xffffffff
+ field @Deprecated public static final int RTT_PEER_NAN = 5; // 0x5
+ field @Deprecated public static final int RTT_PEER_P2P_CLIENT = 4; // 0x4
+ field @Deprecated public static final int RTT_PEER_P2P_GO = 3; // 0x3
+ field @Deprecated public static final int RTT_PEER_TYPE_AP = 1; // 0x1
+ field @Deprecated public static final int RTT_PEER_TYPE_STA = 2; // 0x2
+ field @Deprecated public static final int RTT_PEER_TYPE_UNSPECIFIED = 0; // 0x0
+ field @Deprecated public static final int RTT_STATUS_ABORTED = 8; // 0x8
+ field @Deprecated public static final int RTT_STATUS_FAILURE = 1; // 0x1
+ field @Deprecated public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6; // 0x6
+ field @Deprecated public static final int RTT_STATUS_FAIL_BUSY_TRY_LATER = 12; // 0xc
+ field @Deprecated public static final int RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE = 15; // 0xf
+ field @Deprecated public static final int RTT_STATUS_FAIL_INVALID_TS = 9; // 0x9
+ field @Deprecated public static final int RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4; // 0x4
+ field @Deprecated public static final int RTT_STATUS_FAIL_NO_CAPABILITY = 7; // 0x7
+ field @Deprecated public static final int RTT_STATUS_FAIL_NO_RSP = 2; // 0x2
+ field @Deprecated public static final int RTT_STATUS_FAIL_PROTOCOL = 10; // 0xa
+ field @Deprecated public static final int RTT_STATUS_FAIL_REJECTED = 3; // 0x3
+ field @Deprecated public static final int RTT_STATUS_FAIL_SCHEDULE = 11; // 0xb
+ field @Deprecated public static final int RTT_STATUS_FAIL_TM_TIMEOUT = 5; // 0x5
+ field @Deprecated public static final int RTT_STATUS_INVALID_REQ = 13; // 0xd
+ field @Deprecated public static final int RTT_STATUS_NO_WIFI = 14; // 0xe
+ field @Deprecated public static final int RTT_STATUS_SUCCESS = 0; // 0x0
+ field @Deprecated public static final int RTT_TYPE_11_MC = 4; // 0x4
+ field @Deprecated public static final int RTT_TYPE_11_V = 2; // 0x2
+ field @Deprecated public static final int RTT_TYPE_ONE_SIDED = 1; // 0x1
+ field @Deprecated public static final int RTT_TYPE_TWO_SIDED = 2; // 0x2
+ field @Deprecated public static final int RTT_TYPE_UNSPECIFIED = 0; // 0x0
+ }
+
+ @Deprecated public class RttManager.Capabilities {
+ ctor @Deprecated public RttManager.Capabilities();
+ field @Deprecated public int supportedPeerType;
+ field @Deprecated public int supportedType;
+ }
+
+ @Deprecated public static class RttManager.ParcelableRttParams implements android.os.Parcelable {
+ field @Deprecated @NonNull public android.net.wifi.RttManager.RttParams[] mParams;
+ }
+
+ @Deprecated public static class RttManager.ParcelableRttResults implements android.os.Parcelable {
+ ctor @Deprecated public RttManager.ParcelableRttResults(android.net.wifi.RttManager.RttResult[]);
+ field @Deprecated public android.net.wifi.RttManager.RttResult[] mResults;
+ }
+
+ @Deprecated public abstract static class RttManager.ResponderCallback {
+ ctor @Deprecated public RttManager.ResponderCallback();
+ method @Deprecated public abstract void onResponderEnableFailure(int);
+ method @Deprecated public abstract void onResponderEnabled(android.net.wifi.RttManager.ResponderConfig);
+ }
+
+ @Deprecated public static class RttManager.ResponderConfig implements android.os.Parcelable {
+ ctor @Deprecated public RttManager.ResponderConfig();
+ method @Deprecated public int describeContents();
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.RttManager.ResponderConfig> CREATOR;
+ field @Deprecated public int centerFreq0;
+ field @Deprecated public int centerFreq1;
+ field @Deprecated public int channelWidth;
+ field @Deprecated public int frequency;
+ field @Deprecated public String macAddress;
+ field @Deprecated public int preamble;
+ }
+
+ @Deprecated public static class RttManager.RttCapabilities implements android.os.Parcelable {
+ ctor @Deprecated public RttManager.RttCapabilities();
+ field @Deprecated public int bwSupported;
+ field @Deprecated public boolean lciSupported;
+ field @Deprecated public boolean lcrSupported;
+ field @Deprecated public int mcVersion;
+ field @Deprecated public boolean oneSidedRttSupported;
+ field @Deprecated public int preambleSupported;
+ field @Deprecated public boolean responderSupported;
+ field @Deprecated public boolean secureRttSupported;
+ field @Deprecated public boolean supportedPeerType;
+ field @Deprecated public boolean supportedType;
+ field @Deprecated public boolean twoSided11McRttSupported;
+ }
+
+ @Deprecated public static interface RttManager.RttListener {
+ method @Deprecated public void onAborted();
+ method @Deprecated public void onFailure(int, String);
+ method @Deprecated public void onSuccess(android.net.wifi.RttManager.RttResult[]);
+ }
+
+ @Deprecated public static class RttManager.RttParams {
+ ctor @Deprecated public RttManager.RttParams();
+ field @Deprecated public boolean LCIRequest;
+ field @Deprecated public boolean LCRRequest;
+ field @Deprecated public int bandwidth;
+ field @Deprecated public String bssid;
+ field @Deprecated public int burstTimeout;
+ field @Deprecated public int centerFreq0;
+ field @Deprecated public int centerFreq1;
+ field @Deprecated public int channelWidth;
+ field @Deprecated public int deviceType;
+ field @Deprecated public int frequency;
+ field @Deprecated public int interval;
+ field @Deprecated public int numRetriesPerFTMR;
+ field @Deprecated public int numRetriesPerMeasurementFrame;
+ field @Deprecated public int numSamplesPerBurst;
+ field @Deprecated public int num_retries;
+ field @Deprecated public int num_samples;
+ field @Deprecated public int numberBurst;
+ field @Deprecated public int preamble;
+ field @Deprecated public int requestType;
+ field @Deprecated public boolean secure;
+ }
+
+ @Deprecated public static class RttManager.RttResult {
+ ctor @Deprecated public RttManager.RttResult();
+ field @Deprecated public android.net.wifi.RttManager.WifiInformationElement LCI;
+ field @Deprecated public android.net.wifi.RttManager.WifiInformationElement LCR;
+ field @Deprecated public String bssid;
+ field @Deprecated public int burstDuration;
+ field @Deprecated public int burstNumber;
+ field @Deprecated public int distance;
+ field @Deprecated public int distanceSpread;
+ field @Deprecated public int distanceStandardDeviation;
+ field @Deprecated public int distance_cm;
+ field @Deprecated public int distance_sd_cm;
+ field @Deprecated public int distance_spread_cm;
+ field @Deprecated public int frameNumberPerBurstPeer;
+ field @Deprecated public int measurementFrameNumber;
+ field @Deprecated public int measurementType;
+ field @Deprecated public int negotiatedBurstNum;
+ field @Deprecated public int requestType;
+ field @Deprecated public int retryAfterDuration;
+ field @Deprecated public int rssi;
+ field @Deprecated public int rssiSpread;
+ field @Deprecated public int rssi_spread;
+ field @Deprecated public long rtt;
+ field @Deprecated public long rttSpread;
+ field @Deprecated public long rttStandardDeviation;
+ field @Deprecated public long rtt_ns;
+ field @Deprecated public long rtt_sd_ns;
+ field @Deprecated public long rtt_spread_ns;
+ field @Deprecated public int rxRate;
+ field @Deprecated public boolean secure;
+ field @Deprecated public int status;
+ field @Deprecated public int successMeasurementFrameNumber;
+ field @Deprecated public long ts;
+ field @Deprecated public int txRate;
+ field @Deprecated public int tx_rate;
+ }
+
+ @Deprecated public static class RttManager.WifiInformationElement {
+ ctor @Deprecated public RttManager.WifiInformationElement();
+ field @Deprecated public byte[] data;
+ field @Deprecated public byte id;
+ }
+
+ public class ScanResult implements android.os.Parcelable {
+ 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
+ field public static final int CIPHER_NO_GROUP_ADDRESSED = 1; // 0x1
+ field public static final int CIPHER_SMS4 = 5; // 0x5
+ field public static final int CIPHER_TKIP = 2; // 0x2
+ field public static final int KEY_MGMT_EAP = 2; // 0x2
+ field public static final int KEY_MGMT_EAP_SHA256 = 6; // 0x6
+ field public static final int KEY_MGMT_EAP_SUITE_B_192 = 10; // 0xa
+ field public static final int KEY_MGMT_FT_EAP = 4; // 0x4
+ field public static final int KEY_MGMT_FT_PSK = 3; // 0x3
+ field public static final int KEY_MGMT_FT_SAE = 11; // 0xb
+ field public static final int KEY_MGMT_NONE = 0; // 0x0
+ field public static final int KEY_MGMT_OSEN = 7; // 0x7
+ field public static final int KEY_MGMT_OWE = 9; // 0x9
+ field public static final int KEY_MGMT_OWE_TRANSITION = 12; // 0xc
+ field public static final int KEY_MGMT_PSK = 1; // 0x1
+ field public static final int KEY_MGMT_PSK_SHA256 = 5; // 0x5
+ field public static final int KEY_MGMT_SAE = 8; // 0x8
+ field public static final int KEY_MGMT_WAPI_CERT = 14; // 0xe
+ field public static final int KEY_MGMT_WAPI_PSK = 13; // 0xd
+ field public static final int PROTOCOL_NONE = 0; // 0x0
+ field public static final int PROTOCOL_OSEN = 3; // 0x3
+ field public static final int PROTOCOL_RSN = 2; // 0x2
+ field public static final int PROTOCOL_WAPI = 4; // 0x4
+ field public static final int PROTOCOL_WPA = 1; // 0x1
+ }
+
+ public final class SoftApCapability implements android.os.Parcelable {
+ method public boolean areFeaturesSupported(long);
+ method public int describeContents();
+ method public int getMaxSupportedClients();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApCapability> CREATOR;
+ field public static final long SOFTAP_FEATURE_ACS_OFFLOAD = 1L; // 0x1L
+ field public static final long SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT = 2L; // 0x2L
+ field public static final long SOFTAP_FEATURE_WPA3_SAE = 4L; // 0x4L
+ }
+
+ public final class SoftApConfiguration implements android.os.Parcelable {
+ method @NonNull public java.util.List<android.net.MacAddress> getAllowedClientList();
+ method public int getBand();
+ method @NonNull public java.util.List<android.net.MacAddress> getBlockedClientList();
+ method public int getChannel();
+ method public int getMaxNumberOfClients();
+ method public long getShutdownTimeoutMillis();
+ method public boolean isAutoShutdownEnabled();
+ method public boolean isClientControlByUserEnabled();
+ method @Nullable public android.net.wifi.WifiConfiguration toWifiConfiguration();
+ field public static final int BAND_2GHZ = 1; // 0x1
+ field public static final int BAND_5GHZ = 2; // 0x2
+ field public static final int BAND_6GHZ = 4; // 0x4
+ field public static final int BAND_ANY = 7; // 0x7
+ }
+
+ public static final class SoftApConfiguration.Builder {
+ ctor public SoftApConfiguration.Builder();
+ ctor public SoftApConfiguration.Builder(@NonNull android.net.wifi.SoftApConfiguration);
+ method @NonNull public android.net.wifi.SoftApConfiguration build();
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setAllowedClientList(@NonNull java.util.List<android.net.MacAddress>);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setAutoShutdownEnabled(boolean);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBand(int);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBlockedClientList(@NonNull java.util.List<android.net.MacAddress>);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBssid(@Nullable android.net.MacAddress);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setChannel(int, int);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setClientControlByUserEnabled(boolean);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setHiddenSsid(boolean);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setMaxNumberOfClients(@IntRange(from=0) int);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setPassphrase(@Nullable String, int);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setShutdownTimeoutMillis(@IntRange(from=0) long);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setSsid(@Nullable String);
+ }
+
+ public final class SoftApInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getBandwidth();
+ method public int getFrequency();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CHANNEL_WIDTH_160MHZ = 6; // 0x6
+ field public static final int CHANNEL_WIDTH_20MHZ = 2; // 0x2
+ field public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1; // 0x1
+ field public static final int CHANNEL_WIDTH_40MHZ = 3; // 0x3
+ field public static final int CHANNEL_WIDTH_80MHZ = 4; // 0x4
+ field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5; // 0x5
+ field public static final int CHANNEL_WIDTH_INVALID = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApInfo> CREATOR;
+ }
+
+ public final class WifiClient implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.net.MacAddress getMacAddress();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiClient> CREATOR;
+ }
+
+ @Deprecated public class WifiConfiguration implements android.os.Parcelable {
+ method @Deprecated public int getAuthType();
+ method @Deprecated @NonNull public android.net.IpConfiguration getIpConfiguration();
+ method @Deprecated @NonNull public android.net.wifi.WifiConfiguration.NetworkSelectionStatus getNetworkSelectionStatus();
+ method @Deprecated @NonNull public String getPrintableSsid();
+ method @Deprecated public int getRecentFailureReason();
+ method @Deprecated public boolean hasNoInternetAccess();
+ method @Deprecated public boolean isEphemeral();
+ 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);
+ field @Deprecated public static final int INVALID_NETWORK_ID = -1; // 0xffffffff
+ field @Deprecated public static final int METERED_OVERRIDE_METERED = 1; // 0x1
+ field @Deprecated public static final int METERED_OVERRIDE_NONE = 0; // 0x0
+ field @Deprecated public static final int METERED_OVERRIDE_NOT_METERED = 2; // 0x2
+ field @Deprecated public static final int RANDOMIZATION_NONE = 0; // 0x0
+ field @Deprecated public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
+ field @Deprecated public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; // 0x11
+ field @Deprecated public static final int RECENT_FAILURE_NONE = 0; // 0x0
+ field @Deprecated public boolean allowAutojoin;
+ field @Deprecated public int carrierId;
+ field @Deprecated public String creatorName;
+ field @Deprecated public int creatorUid;
+ field @Deprecated public boolean fromWifiNetworkSpecifier;
+ field @Deprecated public boolean fromWifiNetworkSuggestion;
+ field @Deprecated public String lastUpdateName;
+ field @Deprecated public int lastUpdateUid;
+ field @Deprecated public int macRandomizationSetting;
+ field @Deprecated public boolean meteredHint;
+ field @Deprecated public int meteredOverride;
+ field @Deprecated public int numAssociation;
+ field @Deprecated public int numScorerOverride;
+ field @Deprecated public int numScorerOverrideAndSwitchedNetwork;
+ field @Deprecated public boolean requirePmf;
+ field @Deprecated public boolean shared;
+ field @Deprecated public boolean useExternalScores;
+ }
+
+ @Deprecated public static class WifiConfiguration.KeyMgmt {
+ field @Deprecated public static final int WAPI_CERT = 14; // 0xe
+ field @Deprecated public static final int WAPI_PSK = 13; // 0xd
+ field @Deprecated public static final int WPA2_PSK = 4; // 0x4
+ }
+
+ @Deprecated public static class WifiConfiguration.NetworkSelectionStatus {
+ method @Deprecated public int getDisableReasonCounter(int);
+ method @Deprecated public long getDisableTime();
+ method @Deprecated public static int getMaxNetworkSelectionDisableReason();
+ method @Deprecated public int getNetworkSelectionDisableReason();
+ method @Deprecated @Nullable public static String getNetworkSelectionDisableReasonString(int);
+ method @Deprecated public int getNetworkSelectionStatus();
+ method @Deprecated @NonNull public String getNetworkStatusString();
+ method @Deprecated public boolean hasEverConnected();
+ field @Deprecated public static final int DISABLED_ASSOCIATION_REJECTION = 1; // 0x1
+ field @Deprecated public static final int DISABLED_AUTHENTICATION_FAILURE = 2; // 0x2
+ field @Deprecated public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 5; // 0x5
+ field @Deprecated public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 9; // 0x9
+ field @Deprecated public static final int DISABLED_BY_WIFI_MANAGER = 7; // 0x7
+ field @Deprecated public static final int DISABLED_BY_WRONG_PASSWORD = 8; // 0x8
+ field @Deprecated public static final int DISABLED_DHCP_FAILURE = 3; // 0x3
+ field @Deprecated public static final int DISABLED_NONE = 0; // 0x0
+ field @Deprecated public static final int DISABLED_NO_INTERNET_PERMANENT = 6; // 0x6
+ field @Deprecated public static final int DISABLED_NO_INTERNET_TEMPORARY = 4; // 0x4
+ 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);
+ }
+
+ public class WifiEnterpriseConfig implements android.os.Parcelable {
+ method @Nullable public String[] getCaCertificateAliases();
+ method @NonNull public String getCaPath();
+ method @NonNull public String getClientCertificateAlias();
+ method public int getOcsp();
+ method @NonNull public String getWapiCertSuite();
+ method public void setCaCertificateAliases(@Nullable String[]);
+ method public void setCaPath(@NonNull String);
+ method public void setClientCertificateAlias(@NonNull String);
+ method public void setOcsp(int);
+ method public void setWapiCertSuite(@NonNull String);
+ field public static final int OCSP_NONE = 0; // 0x0
+ field public static final int OCSP_REQUEST_CERT_STATUS = 1; // 0x1
+ field public static final int OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS = 3; // 0x3
+ field public static final int OCSP_REQUIRE_CERT_STATUS = 2; // 0x2
+ }
+
+ public class WifiFrameworkInitializer {
+ method public static void registerServiceWrappers();
+ }
+
+ public class WifiInfo implements android.os.Parcelable {
+ method public double getLostTxPacketsPerSecond();
+ method @Nullable public String getRequestingPackageName();
+ method public double getRetriedTxPacketsPerSecond();
+ method public int getScore();
+ method public double getSuccessfulRxPacketsPerSecond();
+ method public double getSuccessfulTxPacketsPerSecond();
+ method public boolean isEphemeral();
+ method public boolean isOsuAp();
+ method public boolean isPasspointAp();
+ method @Nullable public static String sanitizeSsid(@Nullable String);
+ field public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
+ field public static final int INVALID_RSSI = -127; // 0xffffff81
+ }
+
+ 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);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void allowAutojoinGlobal(boolean);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void allowAutojoinPasspoint(@NonNull String, boolean);
+ method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void clearWifiConnectedNetworkScorer();
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void connect(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void connect(int, @Nullable android.net.wifi.WifiManager.ActionListener);
+ method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void disable(int, @Nullable android.net.wifi.WifiManager.ActionListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK}) public void disableEphemeralNetwork(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void factoryReset();
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void forget(int, @Nullable android.net.wifi.WifiManager.ActionListener);
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.util.Pair<android.net.wifi.WifiConfiguration,java.util.Map<java.lang.Integer,java.util.List<android.net.wifi.ScanResult>>>> getAllMatchingWifiConfigs(@NonNull java.util.List<android.net.wifi.ScanResult>);
+ method @Nullable @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String getCountryCode();
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.Network getCurrentNetwork();
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String[] getFactoryMacAddresses();
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,java.util.List<android.net.wifi.ScanResult>> getMatchingOsuProviders(@Nullable java.util.List<android.net.wifi.ScanResult>);
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.Map<android.net.wifi.hotspot2.OsuProvider,android.net.wifi.hotspot2.PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(@NonNull java.util.Set<android.net.wifi.hotspot2.OsuProvider>);
+ method @NonNull @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE}) public java.util.Map<android.net.wifi.WifiNetworkSuggestion,java.util.List<android.net.wifi.ScanResult>> getMatchingScanResults(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>, @Nullable java.util.List<android.net.wifi.ScanResult>);
+ method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE, android.Manifest.permission.READ_WIFI_CREDENTIAL}) public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public android.net.wifi.SoftApConfiguration getSoftApConfiguration();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public void getWifiActivityEnergyInfoAsync(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.OnWifiActivityEnergyInfoListener);
+ method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getWifiApState();
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(@NonNull java.util.List<android.net.wifi.ScanResult>);
+ method public boolean isApMacRandomizationSupported();
+ method public boolean isConnectedMacRandomizationSupported();
+ method @Deprecated public boolean isDeviceToDeviceRttSupported();
+ method public boolean isPortableHotspotSupported();
+ method public boolean isVerboseLoggingEnabled();
+ method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled();
+ method public boolean isWifiScannerSupported();
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerNetworkRequestMatchCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.NetworkRequestMatchCallback);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerSoftApCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SoftApCallback);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerTrafficStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.TrafficStateCallback);
+ method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void removeOnWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreBackupData(@NonNull byte[]);
+ method @Nullable @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public android.net.wifi.SoftApConfiguration restoreSoftApBackupData(@NonNull byte[]);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreSupplicantBackupData(@NonNull byte[], @NonNull byte[]);
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public byte[] retrieveBackupData();
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public byte[] retrieveSoftApBackupData();
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void save(@NonNull android.net.wifi.WifiConfiguration, @Nullable android.net.wifi.WifiManager.ActionListener);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setAutoWakeupEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) public void setDeviceMobilityState(int);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setMacRandomizationSettingPasspointEnabled(@NonNull String, boolean);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setPasspointMeteredOverride(@NonNull String, int);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setScanAlwaysAvailable(boolean);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setScanThrottleEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public boolean setSoftApConfiguration(@NonNull android.net.wifi.SoftApConfiguration);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setVerboseLoggingEnabled(boolean);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
+ method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public boolean setWifiConnectedNetworkScorer(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.WifiConnectedNetworkScorer);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsEnrolleeInitiator(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startLocalOnlyHotspot(@NonNull android.net.wifi.SoftApConfiguration, @Nullable java.util.concurrent.Executor, @Nullable android.net.wifi.WifiManager.LocalOnlyHotspotCallback);
+ method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public boolean startScan(android.os.WorkSource);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startSubscriptionProvisioning(@NonNull android.net.wifi.hotspot2.OsuProvider, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.hotspot2.ProvisioningCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean startTetheredHotspot(@Nullable android.net.wifi.SoftApConfiguration);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopEasyConnectSession();
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean stopSoftAp();
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterNetworkRequestMatchCallback(@NonNull android.net.wifi.WifiManager.NetworkRequestMatchCallback);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterSoftApCallback(@NonNull android.net.wifi.WifiManager.SoftApCallback);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterTrafficStateCallback(@NonNull android.net.wifi.WifiManager.TrafficStateCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void updateInterfaceIpState(@Nullable String, int);
+ method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void updateWifiUsabilityScore(int, int, int);
+ field public static final String ACTION_LINK_CONFIGURATION_CHANGED = "android.net.wifi.LINK_CONFIGURATION_CHANGED";
+ field @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) public static final String ACTION_NETWORK_SETTINGS_RESET = "android.net.wifi.action.NETWORK_SETTINGS_RESET";
+ field public static final String ACTION_PASSPOINT_LAUNCH_OSU_VIEW = "android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW";
+ field public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE";
+ field public static final String ACTION_REQUEST_ENABLE = "android.net.wifi.action.REQUEST_ENABLE";
+ field public static final int CHANGE_REASON_ADDED = 0; // 0x0
+ field public static final int CHANGE_REASON_CONFIG_CHANGE = 2; // 0x2
+ field public static final int CHANGE_REASON_REMOVED = 1; // 0x1
+ field public static final String CONFIGURED_NETWORKS_CHANGED_ACTION = "android.net.wifi.CONFIGURED_NETWORKS_CHANGE";
+ field public static final int DEVICE_MOBILITY_STATE_HIGH_MVMT = 1; // 0x1
+ field public static final int DEVICE_MOBILITY_STATE_LOW_MVMT = 2; // 0x2
+ field public static final int DEVICE_MOBILITY_STATE_STATIONARY = 3; // 0x3
+ field public static final int DEVICE_MOBILITY_STATE_UNKNOWN = 0; // 0x0
+ field public static final int EASY_CONNECT_NETWORK_ROLE_AP = 1; // 0x1
+ field public static final int EASY_CONNECT_NETWORK_ROLE_STA = 0; // 0x0
+ field public static final String EXTRA_CHANGE_REASON = "changeReason";
+ field public static final String EXTRA_LINK_PROPERTIES = "android.net.wifi.extra.LINK_PROPERTIES";
+ field public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
+ field public static final String EXTRA_OSU_NETWORK = "android.net.wifi.extra.OSU_NETWORK";
+ field public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state";
+ field public static final String EXTRA_URL = "android.net.wifi.extra.URL";
+ field public static final String EXTRA_WIFI_AP_FAILURE_REASON = "android.net.wifi.extra.WIFI_AP_FAILURE_REASON";
+ field public static final String EXTRA_WIFI_AP_INTERFACE_NAME = "android.net.wifi.extra.WIFI_AP_INTERFACE_NAME";
+ field public static final String EXTRA_WIFI_AP_MODE = "android.net.wifi.extra.WIFI_AP_MODE";
+ field public static final String EXTRA_WIFI_AP_STATE = "wifi_state";
+ field public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
+ field public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et";
+ field public static final String EXTRA_WIFI_CREDENTIAL_SSID = "ssid";
+ field public static final int IFACE_IP_MODE_CONFIGURATION_ERROR = 0; // 0x0
+ field public static final int IFACE_IP_MODE_LOCAL_ONLY = 2; // 0x2
+ field public static final int IFACE_IP_MODE_TETHERED = 1; // 0x1
+ field public static final int IFACE_IP_MODE_UNSPECIFIED = -1; // 0xffffffff
+ field public static final int PASSPOINT_HOME_NETWORK = 0; // 0x0
+ field public static final int PASSPOINT_ROAMING_NETWORK = 1; // 0x1
+ field public static final int SAP_CLIENT_BLOCK_REASON_CODE_BLOCKED_BY_USER = 0; // 0x0
+ field public static final int SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS = 1; // 0x1
+ field public static final int SAP_START_FAILURE_GENERAL = 0; // 0x0
+ field public static final int SAP_START_FAILURE_NO_CHANNEL = 1; // 0x1
+ field public static final int SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION = 2; // 0x2
+ field public static final String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED";
+ field public static final int WIFI_AP_STATE_DISABLED = 11; // 0xb
+ field public static final int WIFI_AP_STATE_DISABLING = 10; // 0xa
+ field public static final int WIFI_AP_STATE_ENABLED = 13; // 0xd
+ field public static final int WIFI_AP_STATE_ENABLING = 12; // 0xc
+ field public static final int WIFI_AP_STATE_FAILED = 14; // 0xe
+ field public static final String WIFI_CREDENTIAL_CHANGED_ACTION = "android.net.wifi.WIFI_CREDENTIAL_CHANGED";
+ field public static final int WIFI_CREDENTIAL_FORGOT = 1; // 0x1
+ field public static final int WIFI_CREDENTIAL_SAVED = 0; // 0x0
+ }
+
+ public static interface WifiManager.ActionListener {
+ method public void onFailure(int);
+ method public void onSuccess();
+ }
+
+ public static interface WifiManager.NetworkRequestMatchCallback {
+ method public default void onAbort();
+ method public default void onMatch(@NonNull java.util.List<android.net.wifi.ScanResult>);
+ method public default void onUserSelectionCallbackRegistration(@NonNull android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback);
+ method public default void onUserSelectionConnectFailure(@NonNull android.net.wifi.WifiConfiguration);
+ method public default void onUserSelectionConnectSuccess(@NonNull android.net.wifi.WifiConfiguration);
+ }
+
+ public static interface WifiManager.NetworkRequestUserSelectionCallback {
+ method public default void reject();
+ method public default void select(@NonNull android.net.wifi.WifiConfiguration);
+ }
+
+ public static interface WifiManager.OnWifiActivityEnergyInfoListener {
+ method public void onWifiActivityEnergyInfo(@Nullable android.os.connectivity.WifiActivityEnergyInfo);
+ }
+
+ public static interface WifiManager.OnWifiUsabilityStatsListener {
+ method public void onWifiUsabilityStats(int, boolean, @NonNull android.net.wifi.WifiUsabilityStatsEntry);
+ }
+
+ public static interface WifiManager.ScoreUpdateObserver {
+ method public void notifyScoreUpdate(int, int);
+ method public void triggerUpdateOfWifiUsabilityStats(int);
+ }
+
+ public static interface WifiManager.SoftApCallback {
+ method public default void onBlockedClientConnecting(@NonNull android.net.wifi.WifiClient, int);
+ method public default void onCapabilityChanged(@NonNull android.net.wifi.SoftApCapability);
+ method public default void onConnectedClientsChanged(@NonNull java.util.List<android.net.wifi.WifiClient>);
+ method public default void onInfoChanged(@NonNull android.net.wifi.SoftApInfo);
+ method public default void onStateChanged(int, int);
+ }
+
+ public static interface WifiManager.TrafficStateCallback {
+ method public void onStateChanged(int);
+ field public static final int DATA_ACTIVITY_IN = 1; // 0x1
+ field public static final int DATA_ACTIVITY_INOUT = 3; // 0x3
+ field public static final int DATA_ACTIVITY_NONE = 0; // 0x0
+ field public static final int DATA_ACTIVITY_OUT = 2; // 0x2
+ }
+
+ public static interface WifiManager.WifiConnectedNetworkScorer {
+ method public void onSetScoreUpdateObserver(@NonNull android.net.wifi.WifiManager.ScoreUpdateObserver);
+ method public void onStart(int);
+ method public void onStop(int);
+ }
+
+ public class WifiNetworkConnectionStatistics implements android.os.Parcelable {
+ ctor public WifiNetworkConnectionStatistics(int, int);
+ ctor public WifiNetworkConnectionStatistics();
+ ctor public WifiNetworkConnectionStatistics(android.net.wifi.WifiNetworkConnectionStatistics);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiNetworkConnectionStatistics> CREATOR;
+ field public int numConnection;
+ field public int numUsage;
+ }
+
+ public final class WifiNetworkSuggestion implements android.os.Parcelable {
+ method @NonNull public android.net.wifi.WifiConfiguration getWifiConfiguration();
+ }
+
+ public static final class WifiNetworkSuggestion.Builder {
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) public android.net.wifi.WifiNetworkSuggestion.Builder setCarrierId(int);
+ }
+
+ public class WifiScanner {
+ method @Deprecated public void configureWifiChange(int, int, int, int, int, android.net.wifi.WifiScanner.BssidInfo[]);
+ method @Deprecated public void configureWifiChange(android.net.wifi.WifiScanner.WifiChangeSettings);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<java.lang.Integer> getAvailableChannels(int);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean getScanResults();
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<android.net.wifi.ScanResult> getSingleScanResults();
+ method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void registerScanListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiScanner.ScanListener);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setScanningEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startBackgroundScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startBackgroundScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener, android.os.WorkSource);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener, android.os.WorkSource);
+ method @Deprecated public void startTrackingBssids(android.net.wifi.WifiScanner.BssidInfo[], int, android.net.wifi.WifiScanner.BssidListener);
+ method @Deprecated public void startTrackingWifiChange(android.net.wifi.WifiScanner.WifiChangeListener);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void stopBackgroundScan(android.net.wifi.WifiScanner.ScanListener);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void stopScan(android.net.wifi.WifiScanner.ScanListener);
+ method @Deprecated public void stopTrackingBssids(android.net.wifi.WifiScanner.BssidListener);
+ method @Deprecated public void stopTrackingWifiChange(android.net.wifi.WifiScanner.WifiChangeListener);
+ method public void unregisterScanListener(@NonNull android.net.wifi.WifiScanner.ScanListener);
+ field public static final int MAX_SCAN_PERIOD_MS = 1024000; // 0xfa000
+ field public static final int MIN_SCAN_PERIOD_MS = 1000; // 0x3e8
+ field public static final int REASON_DUPLICATE_REQEUST = -5; // 0xfffffffb
+ field public static final int REASON_INVALID_LISTENER = -2; // 0xfffffffe
+ field public static final int REASON_INVALID_REQUEST = -3; // 0xfffffffd
+ field public static final int REASON_NOT_AUTHORIZED = -4; // 0xfffffffc
+ field public static final int REASON_SUCCEEDED = 0; // 0x0
+ field public static final int REASON_UNSPECIFIED = -1; // 0xffffffff
+ field @Deprecated public static final int REPORT_EVENT_AFTER_BUFFER_FULL = 0; // 0x0
+ field public static final int REPORT_EVENT_AFTER_EACH_SCAN = 1; // 0x1
+ field public static final int REPORT_EVENT_FULL_SCAN_RESULT = 2; // 0x2
+ field public static final int REPORT_EVENT_NO_BATCH = 4; // 0x4
+ field public static final int SCAN_TYPE_HIGH_ACCURACY = 2; // 0x2
+ field public static final int SCAN_TYPE_LOW_LATENCY = 0; // 0x0
+ field public static final int SCAN_TYPE_LOW_POWER = 1; // 0x1
+ field public static final int WIFI_BAND_24_5_6_GHZ = 11; // 0xb
+ field public static final int WIFI_BAND_24_5_WITH_DFS_6_GHZ = 15; // 0xf
+ field public static final int WIFI_BAND_24_GHZ = 1; // 0x1
+ field public static final int WIFI_BAND_5_GHZ = 2; // 0x2
+ field public static final int WIFI_BAND_5_GHZ_DFS_ONLY = 4; // 0x4
+ field public static final int WIFI_BAND_5_GHZ_WITH_DFS = 6; // 0x6
+ field public static final int WIFI_BAND_6_GHZ = 8; // 0x8
+ field public static final int WIFI_BAND_BOTH = 3; // 0x3
+ field public static final int WIFI_BAND_BOTH_WITH_DFS = 7; // 0x7
+ field public static final int WIFI_BAND_UNSPECIFIED = 0; // 0x0
+ }
+
+ public static interface WifiScanner.ActionListener {
+ method public void onFailure(int, String);
+ method public void onSuccess();
+ }
+
+ @Deprecated public static class WifiScanner.BssidInfo {
+ ctor @Deprecated public WifiScanner.BssidInfo();
+ field @Deprecated public String bssid;
+ field @Deprecated public int frequencyHint;
+ field @Deprecated public int high;
+ field @Deprecated public int low;
+ }
+
+ @Deprecated public static interface WifiScanner.BssidListener extends android.net.wifi.WifiScanner.ActionListener {
+ method @Deprecated public void onFound(android.net.wifi.ScanResult[]);
+ method @Deprecated public void onLost(android.net.wifi.ScanResult[]);
+ }
+
+ public static class WifiScanner.ChannelSpec {
+ ctor public WifiScanner.ChannelSpec(int);
+ field public int frequency;
+ }
+
+ @Deprecated public static class WifiScanner.HotlistSettings implements android.os.Parcelable {
+ ctor @Deprecated public WifiScanner.HotlistSettings();
+ field @Deprecated public int apLostThreshold;
+ field @Deprecated public android.net.wifi.WifiScanner.BssidInfo[] bssidInfos;
+ }
+
+ public static class WifiScanner.ParcelableScanData implements android.os.Parcelable {
+ ctor public WifiScanner.ParcelableScanData(android.net.wifi.WifiScanner.ScanData[]);
+ method public android.net.wifi.WifiScanner.ScanData[] getResults();
+ field public android.net.wifi.WifiScanner.ScanData[] mResults;
+ }
+
+ public static class WifiScanner.ParcelableScanResults implements android.os.Parcelable {
+ ctor public WifiScanner.ParcelableScanResults(android.net.wifi.ScanResult[]);
+ method public android.net.wifi.ScanResult[] getResults();
+ field public android.net.wifi.ScanResult[] mResults;
+ }
+
+ public static class WifiScanner.ScanData implements android.os.Parcelable {
+ ctor public WifiScanner.ScanData(int, int, android.net.wifi.ScanResult[]);
+ ctor public WifiScanner.ScanData(android.net.wifi.WifiScanner.ScanData);
+ method public int getFlags();
+ method public int getId();
+ method public android.net.wifi.ScanResult[] getResults();
+ }
+
+ public static interface WifiScanner.ScanListener extends android.net.wifi.WifiScanner.ActionListener {
+ method public void onFullResult(android.net.wifi.ScanResult);
+ method @Deprecated public void onPeriodChanged(int);
+ method public void onResults(android.net.wifi.WifiScanner.ScanData[]);
+ }
+
+ public static class WifiScanner.ScanSettings implements android.os.Parcelable {
+ ctor public WifiScanner.ScanSettings();
+ field public int band;
+ field public android.net.wifi.WifiScanner.ChannelSpec[] channels;
+ field @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public final java.util.List<android.net.wifi.WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworks;
+ field public boolean hideFromAppOps;
+ field public boolean ignoreLocationSettings;
+ field @Deprecated public int maxPeriodInMs;
+ field @Deprecated public int maxScansToCache;
+ field @Deprecated public int numBssidsPerScan;
+ field @Deprecated public int periodInMs;
+ field @Deprecated public int reportEvents;
+ field @Deprecated public int stepCount;
+ field @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public int type;
+ }
+
+ public static class WifiScanner.ScanSettings.HiddenNetwork {
+ ctor public WifiScanner.ScanSettings.HiddenNetwork(@NonNull String);
+ field @NonNull public final String ssid;
+ }
+
+ @Deprecated public static interface WifiScanner.WifiChangeListener extends android.net.wifi.WifiScanner.ActionListener {
+ method @Deprecated public void onChanging(android.net.wifi.ScanResult[]);
+ method @Deprecated public void onQuiescence(android.net.wifi.ScanResult[]);
+ }
+
+ @Deprecated public static class WifiScanner.WifiChangeSettings implements android.os.Parcelable {
+ ctor @Deprecated public WifiScanner.WifiChangeSettings();
+ field @Deprecated public android.net.wifi.WifiScanner.BssidInfo[] bssidInfos;
+ field @Deprecated public int lostApSampleSize;
+ field @Deprecated public int minApsBreachingThreshold;
+ field @Deprecated public int periodInMs;
+ field @Deprecated public int rssiSampleSize;
+ field @Deprecated public int unchangedSampleSize;
+ }
+
+ public final class WifiUsabilityStatsEntry implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getCellularDataNetworkType();
+ method public int getCellularSignalStrengthDb();
+ method public int getCellularSignalStrengthDbm();
+ method public int getLinkSpeedMbps();
+ method public int getProbeElapsedTimeSinceLastUpdateMillis();
+ method public int getProbeMcsRateSinceLastUpdate();
+ method public int getProbeStatusSinceLastUpdate();
+ method public int getRssi();
+ method public int getRxLinkSpeedMbps();
+ method public long getTimeStampMillis();
+ method public long getTotalBackgroundScanTimeMillis();
+ method public long getTotalBeaconRx();
+ method public long getTotalCcaBusyFreqTimeMillis();
+ method public long getTotalHotspot2ScanTimeMillis();
+ method public long getTotalNanScanTimeMillis();
+ method public long getTotalPnoScanTimeMillis();
+ method public long getTotalRadioOnFreqTimeMillis();
+ method public long getTotalRadioOnTimeMillis();
+ method public long getTotalRadioRxTimeMillis();
+ method public long getTotalRadioTxTimeMillis();
+ method public long getTotalRoamScanTimeMillis();
+ method public long getTotalRxSuccess();
+ method public long getTotalScanTimeMillis();
+ method public long getTotalTxBad();
+ method public long getTotalTxRetries();
+ method public long getTotalTxSuccess();
+ method public boolean isSameRegisteredCell();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiUsabilityStatsEntry> CREATOR;
+ field public static final int PROBE_STATUS_FAILURE = 3; // 0x3
+ field public static final int PROBE_STATUS_NO_PROBE = 1; // 0x1
+ field public static final int PROBE_STATUS_SUCCESS = 2; // 0x2
+ field public static final int PROBE_STATUS_UNKNOWN = 0; // 0x0
+ }
+
+}
+
+package android.net.wifi.aware {
+
+ public class DiscoverySession implements java.lang.AutoCloseable {
+ method @Deprecated public android.net.NetworkSpecifier createNetworkSpecifierPmk(@NonNull android.net.wifi.aware.PeerHandle, @NonNull byte[]);
+ }
+
+ public class WifiAwareSession implements java.lang.AutoCloseable {
+ method public android.net.NetworkSpecifier createNetworkSpecifierPmk(int, @NonNull byte[], @NonNull byte[]);
+ }
+
+}
+
+package android.net.wifi.hotspot2 {
+
+ public final class OsuProvider implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public String getFriendlyName();
+ method @Nullable public android.net.Uri getServerUri();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.OsuProvider> CREATOR;
+ }
+
+ public final class PasspointConfiguration implements android.os.Parcelable {
+ method public int getMeteredOverride();
+ method public boolean isAutojoinEnabled();
+ method public boolean isMacRandomizationEnabled();
+ }
+
+ public abstract class ProvisioningCallback {
+ ctor public ProvisioningCallback();
+ method public abstract void onProvisioningComplete();
+ method public abstract void onProvisioningFailure(int);
+ method public abstract void onProvisioningStatus(int);
+ field public static final int OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION = 22; // 0x16
+ field public static final int OSU_FAILURE_AP_CONNECTION = 1; // 0x1
+ field public static final int OSU_FAILURE_INVALID_URL_FORMAT_FOR_OSU = 8; // 0x8
+ field public static final int OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE = 17; // 0x11
+ field public static final int OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE = 21; // 0x15
+ field public static final int OSU_FAILURE_NO_OSU_ACTIVITY_FOUND = 14; // 0xe
+ field public static final int OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE = 19; // 0x13
+ field public static final int OSU_FAILURE_NO_PPS_MO = 16; // 0x10
+ field public static final int OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE = 18; // 0x12
+ field public static final int OSU_FAILURE_OSU_PROVIDER_NOT_FOUND = 23; // 0x17
+ field public static final int OSU_FAILURE_PROVISIONING_ABORTED = 6; // 0x6
+ field public static final int OSU_FAILURE_PROVISIONING_NOT_AVAILABLE = 7; // 0x7
+ field public static final int OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES = 20; // 0x14
+ field public static final int OSU_FAILURE_SERVER_CONNECTION = 3; // 0x3
+ field public static final int OSU_FAILURE_SERVER_URL_INVALID = 2; // 0x2
+ field public static final int OSU_FAILURE_SERVER_VALIDATION = 4; // 0x4
+ field public static final int OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION = 5; // 0x5
+ field public static final int OSU_FAILURE_SOAP_MESSAGE_EXCHANGE = 11; // 0xb
+ field public static final int OSU_FAILURE_START_REDIRECT_LISTENER = 12; // 0xc
+ field public static final int OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER = 13; // 0xd
+ field public static final int OSU_FAILURE_UNEXPECTED_COMMAND_TYPE = 9; // 0x9
+ field public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS = 15; // 0xf
+ field public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE = 10; // 0xa
+ field public static final int OSU_STATUS_AP_CONNECTED = 2; // 0x2
+ field public static final int OSU_STATUS_AP_CONNECTING = 1; // 0x1
+ field public static final int OSU_STATUS_INIT_SOAP_EXCHANGE = 6; // 0x6
+ field public static final int OSU_STATUS_REDIRECT_RESPONSE_RECEIVED = 8; // 0x8
+ field public static final int OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS = 11; // 0xb
+ field public static final int OSU_STATUS_SECOND_SOAP_EXCHANGE = 9; // 0x9
+ field public static final int OSU_STATUS_SERVER_CONNECTED = 5; // 0x5
+ field public static final int OSU_STATUS_SERVER_CONNECTING = 3; // 0x3
+ field public static final int OSU_STATUS_SERVER_VALIDATED = 4; // 0x4
+ field public static final int OSU_STATUS_THIRD_SOAP_EXCHANGE = 10; // 0xa
+ field public static final int OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE = 7; // 0x7
+ }
+
+}
+
+package android.net.wifi.p2p {
+
+ public final class WifiP2pGroupList implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.net.wifi.p2p.WifiP2pGroup> getGroupList();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pGroupList> CREATOR;
+ }
+
+ public class WifiP2pManager {
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.OVERRIDE_WIFI_CONFIG}) public void deletePersistentGroup(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, int, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void factoryReset(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.READ_WIFI_CREDENTIAL}) public void requestPersistentGroupInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pManager.PersistentGroupInfoListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.OVERRIDE_WIFI_CONFIG}) public void setDeviceName(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull String, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @RequiresPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) public void setMiracastMode(int);
+ method @RequiresPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) public void setWfdInfo(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @NonNull android.net.wifi.p2p.WifiP2pWfdInfo, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.OVERRIDE_WIFI_CONFIG}) public void setWifiP2pChannels(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, int, int, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void startListening(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void stopListening(@NonNull android.net.wifi.p2p.WifiP2pManager.Channel, @Nullable android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ field public static final String ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED = "android.net.wifi.p2p.action.WIFI_P2P_PERSISTENT_GROUPS_CHANGED";
+ field public static final int MIRACAST_DISABLED = 0; // 0x0
+ field public static final int MIRACAST_SINK = 2; // 0x2
+ field public static final int MIRACAST_SOURCE = 1; // 0x1
+ }
+
+ public static interface WifiP2pManager.PersistentGroupInfoListener {
+ method public void onPersistentGroupInfoAvailable(@NonNull android.net.wifi.p2p.WifiP2pGroupList);
+ }
+
+}
+
+package android.net.wifi.rtt {
+
+ public static final class RangingRequest.Builder {
+ method public android.net.wifi.rtt.RangingRequest.Builder addResponder(@NonNull android.net.wifi.rtt.ResponderConfig);
+ }
+
+ public final class RangingResult implements android.os.Parcelable {
+ method @NonNull public byte[] getLci();
+ method @NonNull public byte[] getLcr();
+ }
+
+ public final class ResponderConfig implements android.os.Parcelable {
+ ctor public ResponderConfig(@NonNull android.net.MacAddress, int, boolean, int, int, int, int, int);
+ ctor public ResponderConfig(@NonNull android.net.wifi.aware.PeerHandle, int, boolean, int, int, int, int, int);
+ method public int describeContents();
+ method public static android.net.wifi.rtt.ResponderConfig fromScanResult(android.net.wifi.ScanResult);
+ method public static android.net.wifi.rtt.ResponderConfig fromWifiAwarePeerHandleWithDefaults(android.net.wifi.aware.PeerHandle);
+ method public static android.net.wifi.rtt.ResponderConfig fromWifiAwarePeerMacAddressWithDefaults(android.net.MacAddress);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CHANNEL_WIDTH_160MHZ = 3; // 0x3
+ field public static final int CHANNEL_WIDTH_20MHZ = 0; // 0x0
+ field public static final int CHANNEL_WIDTH_40MHZ = 1; // 0x1
+ field public static final int CHANNEL_WIDTH_80MHZ = 2; // 0x2
+ field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; // 0x4
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.ResponderConfig> CREATOR;
+ field public static final int PREAMBLE_HE = 3; // 0x3
+ field public static final int PREAMBLE_HT = 1; // 0x1
+ field public static final int PREAMBLE_LEGACY = 0; // 0x0
+ field public static final int PREAMBLE_VHT = 2; // 0x2
+ field public static final int RESPONDER_AP = 0; // 0x0
+ field public static final int RESPONDER_AWARE = 4; // 0x4
+ field public static final int RESPONDER_P2P_CLIENT = 3; // 0x3
+ field public static final int RESPONDER_P2P_GO = 2; // 0x2
+ field public static final int RESPONDER_STA = 1; // 0x1
+ field public final int centerFreq0;
+ field public final int centerFreq1;
+ field public final int channelWidth;
+ field public final int frequency;
+ field public final android.net.MacAddress macAddress;
+ field public final android.net.wifi.aware.PeerHandle peerHandle;
+ field public final int preamble;
+ field public final int responderType;
+ field public final boolean supports80211mc;
+ }
+
+ public final class ResponderLocation implements android.os.Parcelable {
+ method public boolean getExtraInfoOnAssociationIndication();
+ }
+
+ public class WifiRttManager {
+ method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE}) public void cancelRanging(@Nullable android.os.WorkSource);
+ method @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.ACCESS_WIFI_STATE}) public void startRanging(@Nullable android.os.WorkSource, @NonNull android.net.wifi.rtt.RangingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.rtt.RangingResultCallback);
+ }
+
+}
+
diff --git a/wifi/api/system-removed.txt b/wifi/api/system-removed.txt
new file mode 100644
index 0000000..35f9726
--- /dev/null
+++ b/wifi/api/system-removed.txt
@@ -0,0 +1,16 @@
+// Signature format: 2.0
+package android.net.wifi {
+
+ @Deprecated public class BatchedScanResult implements android.os.Parcelable {
+ ctor public BatchedScanResult();
+ ctor public BatchedScanResult(android.net.wifi.BatchedScanResult);
+ field public final java.util.List<android.net.wifi.ScanResult> scanResults;
+ field public boolean truncated;
+ }
+
+ public class ScanResult implements android.os.Parcelable {
+ field public boolean untrusted;
+ }
+
+}
+
diff --git a/wifi/java/android/net/wifi/SoftApConfToXmlMigrationUtil.java b/wifi/java/android/net/wifi/SoftApConfToXmlMigrationUtil.java
new file mode 100755
index 0000000..c5472ce
--- /dev/null
+++ b/wifi/java/android/net/wifi/SoftApConfToXmlMigrationUtil.java
@@ -0,0 +1,284 @@
+/*
+ * 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.net.wifi;
+
+import static android.os.Environment.getDataMiscDirectory;
+
+import android.annotation.Nullable;
+import android.net.MacAddress;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Utility class to convert the legacy softap.conf file format to the new XML format.
+ * Note:
+ * <li>This should be modified by the OEM if they want to migrate configuration for existing
+ * devices for new softap features supported by AOSP in Android 11.
+ * For ex: client allowlist/blocklist feature was already supported by some OEM's before Android 10
+ * while AOSP only supported it in Android 11. </li>
+ * <li>Most of this class was copied over from WifiApConfigStore class in Android 10 and
+ * SoftApStoreData class in Android 11</li>
+ * @hide
+ */
+public final class SoftApConfToXmlMigrationUtil {
+ private static final String TAG = "SoftApConfToXmlMigrationUtil";
+
+ /**
+ * Directory to read the wifi config store files from under.
+ */
+ private static final String LEGACY_WIFI_STORE_DIRECTORY_NAME = "wifi";
+ /**
+ * The legacy Softap config file which contained key/value pairs.
+ */
+ private static final String LEGACY_AP_CONFIG_FILE = "softap.conf";
+
+ /**
+ * Pre-apex wifi shared folder.
+ */
+ private static File getLegacyWifiSharedDirectory() {
+ return new File(getDataMiscDirectory(), LEGACY_WIFI_STORE_DIRECTORY_NAME);
+ }
+
+ /* @hide constants copied from WifiConfiguration */
+ /**
+ * 2GHz band.
+ */
+ private static final int WIFICONFIG_AP_BAND_2GHZ = 0;
+ /**
+ * 5GHz band.
+ */
+ private static final int WIFICONFIG_AP_BAND_5GHZ = 1;
+ /**
+ * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability,
+ * operating country code and current radio conditions.
+ */
+ private static final int WIFICONFIG_AP_BAND_ANY = -1;
+ /**
+ * Convert band from WifiConfiguration into SoftApConfiguration
+ *
+ * @param wifiConfigBand band encoded as WIFICONFIG_AP_BAND_xxxx
+ * @return band as encoded as SoftApConfiguration.BAND_xxx
+ */
+ @VisibleForTesting
+ public static int convertWifiConfigBandToSoftApConfigBand(int wifiConfigBand) {
+ switch (wifiConfigBand) {
+ case WIFICONFIG_AP_BAND_2GHZ:
+ return SoftApConfiguration.BAND_2GHZ;
+ case WIFICONFIG_AP_BAND_5GHZ:
+ return SoftApConfiguration.BAND_5GHZ;
+ case WIFICONFIG_AP_BAND_ANY:
+ return SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ;
+ default:
+ return SoftApConfiguration.BAND_2GHZ;
+ }
+ }
+
+ /**
+ * Load AP configuration from legacy persistent storage.
+ * Note: This is deprecated and only used for migrating data once on reboot.
+ */
+ private static SoftApConfiguration loadFromLegacyFile(InputStream fis) {
+ SoftApConfiguration config = null;
+ DataInputStream in = null;
+ try {
+ SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
+ in = new DataInputStream(new BufferedInputStream(fis));
+
+ int version = in.readInt();
+ if (version < 1 || version > 3) {
+ Log.e(TAG, "Bad version on hotspot configuration file");
+ return null;
+ }
+ configBuilder.setSsid(in.readUTF());
+
+ if (version >= 2) {
+ int band = in.readInt();
+ int channel = in.readInt();
+ if (channel == 0) {
+ configBuilder.setBand(
+ convertWifiConfigBandToSoftApConfigBand(band));
+ } else {
+ configBuilder.setChannel(channel,
+ convertWifiConfigBandToSoftApConfigBand(band));
+ }
+ }
+ if (version >= 3) {
+ configBuilder.setHiddenSsid(in.readBoolean());
+ }
+ int authType = in.readInt();
+ if (authType == WifiConfiguration.KeyMgmt.WPA2_PSK) {
+ configBuilder.setPassphrase(in.readUTF(),
+ SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+ }
+ config = configBuilder.build();
+ } catch (IOException e) {
+ Log.e(TAG, "Error reading hotspot configuration ", e);
+ config = null;
+ } catch (IllegalArgumentException ie) {
+ Log.e(TAG, "Invalid hotspot configuration ", ie);
+ config = null;
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Error closing hotspot configuration during read", e);
+ }
+ }
+ }
+ // NOTE: OEM's should add their customized parsing code here.
+ return config;
+ }
+
+ // This is the version that Android 11 released with.
+ private static final int CONFIG_STORE_DATA_VERSION = 3;
+
+ private static final String XML_TAG_DOCUMENT_HEADER = "WifiConfigStoreData";
+ private static final String XML_TAG_VERSION = "Version";
+ private static final String XML_TAG_SECTION_HEADER_SOFTAP = "SoftAp";
+ private static final String XML_TAG_SSID = "SSID";
+ private static final String XML_TAG_BSSID = "Bssid";
+ private static final String XML_TAG_CHANNEL = "Channel";
+ private static final String XML_TAG_HIDDEN_SSID = "HiddenSSID";
+ private static final String XML_TAG_SECURITY_TYPE = "SecurityType";
+ private static final String XML_TAG_AP_BAND = "ApBand";
+ private static final String XML_TAG_PASSPHRASE = "Passphrase";
+ private static final String XML_TAG_MAX_NUMBER_OF_CLIENTS = "MaxNumberOfClients";
+ private static final String XML_TAG_AUTO_SHUTDOWN_ENABLED = "AutoShutdownEnabled";
+ private static final String XML_TAG_SHUTDOWN_TIMEOUT_MILLIS = "ShutdownTimeoutMillis";
+ private static final String XML_TAG_CLIENT_CONTROL_BY_USER = "ClientControlByUser";
+ private static final String XML_TAG_BLOCKED_CLIENT_LIST = "BlockedClientList";
+ private static final String XML_TAG_ALLOWED_CLIENT_LIST = "AllowedClientList";
+ public static final String XML_TAG_CLIENT_MACADDRESS = "ClientMacAddress";
+
+ private static byte[] convertConfToXml(SoftApConfiguration softApConf) {
+ try {
+ final XmlSerializer out = new FastXmlSerializer();
+ final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ out.setOutput(outputStream, StandardCharsets.UTF_8.name());
+
+ // Header for the XML file.
+ out.startDocument(null, true);
+ out.startTag(null, XML_TAG_DOCUMENT_HEADER);
+ XmlUtils.writeValueXml(CONFIG_STORE_DATA_VERSION, XML_TAG_VERSION, out);
+ out.startTag(null, XML_TAG_SECTION_HEADER_SOFTAP);
+
+ // SoftAp conf
+ XmlUtils.writeValueXml(softApConf.getSsid(), XML_TAG_SSID, out);
+ if (softApConf.getBssid() != null) {
+ XmlUtils.writeValueXml(softApConf.getBssid().toString(), XML_TAG_BSSID, out);
+ }
+ XmlUtils.writeValueXml(softApConf.getBand(), XML_TAG_AP_BAND, out);
+ XmlUtils.writeValueXml(softApConf.getChannel(), XML_TAG_CHANNEL, out);
+ XmlUtils.writeValueXml(softApConf.isHiddenSsid(), XML_TAG_HIDDEN_SSID, out);
+ XmlUtils.writeValueXml(softApConf.getSecurityType(), XML_TAG_SECURITY_TYPE, out);
+ if (softApConf.getSecurityType() != SoftApConfiguration.SECURITY_TYPE_OPEN) {
+ XmlUtils.writeValueXml(softApConf.getPassphrase(), XML_TAG_PASSPHRASE, out);
+ }
+ XmlUtils.writeValueXml(softApConf.getMaxNumberOfClients(),
+ XML_TAG_MAX_NUMBER_OF_CLIENTS, out);
+ XmlUtils.writeValueXml(softApConf.isClientControlByUserEnabled(),
+ XML_TAG_CLIENT_CONTROL_BY_USER, out);
+ XmlUtils.writeValueXml(softApConf.isAutoShutdownEnabled(),
+ XML_TAG_AUTO_SHUTDOWN_ENABLED, out);
+ XmlUtils.writeValueXml(softApConf.getShutdownTimeoutMillis(),
+ XML_TAG_SHUTDOWN_TIMEOUT_MILLIS, out);
+ out.startTag(null, XML_TAG_BLOCKED_CLIENT_LIST);
+ for (MacAddress mac: softApConf.getBlockedClientList()) {
+ XmlUtils.writeValueXml(mac.toString(), XML_TAG_CLIENT_MACADDRESS, out);
+ }
+ out.endTag(null, XML_TAG_BLOCKED_CLIENT_LIST);
+ out.startTag(null, XML_TAG_ALLOWED_CLIENT_LIST);
+ for (MacAddress mac: softApConf.getAllowedClientList()) {
+ XmlUtils.writeValueXml(mac.toString(), XML_TAG_CLIENT_MACADDRESS, out);
+ }
+ out.endTag(null, XML_TAG_ALLOWED_CLIENT_LIST);
+
+ // Footer for the XML file.
+ out.endTag(null, XML_TAG_SECTION_HEADER_SOFTAP);
+ out.endTag(null, XML_TAG_DOCUMENT_HEADER);
+ out.endDocument();
+
+ return outputStream.toByteArray();
+ } catch (IOException | XmlPullParserException e) {
+ Log.e(TAG, "Failed to convert softap conf to XML", e);
+ return null;
+ }
+ }
+
+ private SoftApConfToXmlMigrationUtil() { }
+
+ /**
+ * Read the legacy /data/misc/wifi/softap.conf file format and convert to the new XML
+ * format understood by WifiConfigStore.
+ * Note: Used for unit testing.
+ */
+ @VisibleForTesting
+ @Nullable
+ public static InputStream convert(InputStream fis) {
+ SoftApConfiguration softApConf = loadFromLegacyFile(fis);
+ if (softApConf == null) return null;
+
+ byte[] xmlBytes = convertConfToXml(softApConf);
+ if (xmlBytes == null) return null;
+
+ return new ByteArrayInputStream(xmlBytes);
+ }
+
+ /**
+ * Read the legacy /data/misc/wifi/softap.conf file format and convert to the new XML
+ * format understood by WifiConfigStore.
+ */
+ @Nullable
+ public static InputStream convert() {
+ File file = new File(getLegacyWifiSharedDirectory(), LEGACY_AP_CONFIG_FILE);
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ return null;
+ }
+ if (fis == null) return null;
+ return convert(fis);
+ }
+
+ /**
+ * Remove the legacy /data/misc/wifi/softap.conf file.
+ */
+ @Nullable
+ public static void remove() {
+ File file = new File(getLegacyWifiSharedDirectory(), LEGACY_AP_CONFIG_FILE);
+ file.delete();
+ }
+}
diff --git a/wifi/java/android/net/wifi/WifiMigration.java b/wifi/java/android/net/wifi/WifiMigration.java
index 008b18b..666d72d 100755
--- a/wifi/java/android/net/wifi/WifiMigration.java
+++ b/wifi/java/android/net/wifi/WifiMigration.java
@@ -16,25 +16,273 @@
package android.net.wifi;
+import static android.os.Environment.getDataMiscCeDirectory;
+import static android.os.Environment.getDataMiscDirectory;
+
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
import android.provider.Settings;
+import android.util.AtomicFile;
+import android.util.SparseArray;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
/**
* Class used to provide one time hooks for existing OEM devices to migrate their config store
- * data and other settings to the wifi mainline module.
+ * data and other settings to the wifi apex.
* @hide
*/
@SystemApi
public final class WifiMigration {
+ /**
+ * Directory to read the wifi config store files from under.
+ */
+ private static final String LEGACY_WIFI_STORE_DIRECTORY_NAME = "wifi";
+ /**
+ * Config store file for general shared store file.
+ * AOSP Path on Android 10: /data/misc/wifi/WifiConfigStore.xml
+ */
+ public static final int STORE_FILE_SHARED_GENERAL = 0;
+ /**
+ * Config store file for softap shared store file.
+ * AOSP Path on Android 10: /data/misc/wifi/softap.conf
+ */
+ public static final int STORE_FILE_SHARED_SOFTAP = 1;
+ /**
+ * Config store file for general user store file.
+ * AOSP Path on Android 10: /data/misc_ce/<userId>/wifi/WifiConfigStore.xml
+ */
+ public static final int STORE_FILE_USER_GENERAL = 2;
+ /**
+ * Config store file for network suggestions user store file.
+ * AOSP Path on Android 10: /data/misc_ce/<userId>/wifi/WifiConfigStoreNetworkSuggestions.xml
+ */
+ public static final int STORE_FILE_USER_NETWORK_SUGGESTIONS = 3;
+
+ /** @hide */
+ @IntDef(prefix = { "STORE_FILE_SHARED_" }, value = {
+ STORE_FILE_SHARED_GENERAL,
+ STORE_FILE_SHARED_SOFTAP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SharedStoreFileId { }
+
+ /** @hide */
+ @IntDef(prefix = { "STORE_FILE_USER_" }, value = {
+ STORE_FILE_USER_GENERAL,
+ STORE_FILE_USER_NETWORK_SUGGESTIONS
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UserStoreFileId { }
+
+ /**
+ * Mapping of Store file Id to Store file names.
+ *
+ * NOTE: This is the default path for the files on AOSP devices. If the OEM has modified
+ * the path or renamed the files, please edit this appropriately.
+ */
+ private static final SparseArray<String> STORE_ID_TO_FILE_NAME =
+ new SparseArray<String>() {{
+ put(STORE_FILE_SHARED_GENERAL, "WifiConfigStore.xml");
+ put(STORE_FILE_SHARED_SOFTAP, "WifiConfigStoreSoftAp.xml");
+ put(STORE_FILE_USER_GENERAL, "WifiConfigStore.xml");
+ put(STORE_FILE_USER_NETWORK_SUGGESTIONS, "WifiConfigStoreNetworkSuggestions.xml");
+ }};
+
+ /**
+ * Pre-apex wifi shared folder.
+ */
+ private static File getLegacyWifiSharedDirectory() {
+ return new File(getDataMiscDirectory(), LEGACY_WIFI_STORE_DIRECTORY_NAME);
+ }
+
+ /**
+ * Pre-apex wifi user folder.
+ */
+ private static File getLegacyWifiUserDirectory(int userId) {
+ return new File(getDataMiscCeDirectory(userId), LEGACY_WIFI_STORE_DIRECTORY_NAME);
+ }
+
+ /**
+ * Legacy files were stored as AtomicFile. So, always use AtomicFile to operate on it to ensure
+ * data integrity.
+ */
+ private static AtomicFile getSharedAtomicFile(@SharedStoreFileId int storeFileId) {
+ return new AtomicFile(new File(
+ getLegacyWifiSharedDirectory(),
+ STORE_ID_TO_FILE_NAME.get(storeFileId)));
+ }
+
+ /**
+ * Legacy files were stored as AtomicFile. So, always use AtomicFile to operate on it to ensure
+ * data integrity.
+ */
+ private static AtomicFile getUserAtomicFile(@UserStoreFileId int storeFileId, int userId) {
+ return new AtomicFile(new File(
+ getLegacyWifiUserDirectory(userId),
+ STORE_ID_TO_FILE_NAME.get(storeFileId)));
+ }
private WifiMigration() { }
/**
+ * Load data from legacy shared wifi config store file.
+ * TODO(b/149418926): Add XSD for the AOSP file format for each file from R.
+ * <p>
+ * Note:
+ * <li>OEMs need to change the implementation of
+ * {@link #convertAndRetrieveSharedConfigStoreFile(int)} only if their existing config store
+ * format or file locations differs from the vanilla AOSP implementation.</li>
+ * <li>The wifi apex will invoke
+ * {@link #convertAndRetrieveSharedConfigStoreFile(int)}
+ * method on every bootup, it is the responsibility of the OEM implementation to ensure that
+ * they perform the necessary in place conversion of their config store file to conform to the
+ * AOSP format. The OEM should ensure that the method should only return the
+ * {@link InputStream} stream for the data to be migrated only on the first bootup.</li>
+ * <li>Once the migration is done, the apex will invoke
+ * {@link #removeSharedConfigStoreFile(int)} to delete the store file.</li>
+ * <li>The only relevant invocation of {@link #convertAndRetrieveSharedConfigStoreFile(int)}
+ * occurs when a previously released device upgrades to the wifi apex from an OEM
+ * implementation of the wifi stack.
+ * <li>Ensure that the legacy file paths are accessible to the wifi module (sepolicy rules, file
+ * permissions, etc). Since the wifi service continues to run inside system_server process, this
+ * method will be called from the same context (so ideally the file should still be accessible).
+ * </li>
+ *
+ * @param storeFileId Identifier for the config store file. One of
+ * {@link #STORE_FILE_SHARED_GENERAL} or {@link #STORE_FILE_SHARED_GENERAL}
+ * @return Instance of {@link InputStream} for migrating data, null if no migration is
+ * necessary.
+ * @throws IllegalArgumentException on invalid storeFileId.
+ */
+ @Nullable
+ public static InputStream convertAndRetrieveSharedConfigStoreFile(
+ @SharedStoreFileId int storeFileId) {
+ if (storeFileId != STORE_FILE_SHARED_GENERAL && storeFileId != STORE_FILE_SHARED_SOFTAP) {
+ throw new IllegalArgumentException("Invalid shared store file id");
+ }
+ try {
+ // OEMs should do conversions necessary here before returning the stream.
+ return getSharedAtomicFile(storeFileId).openRead();
+ } catch (FileNotFoundException e) {
+ // Special handling for softap.conf.
+ // Note: OEM devices upgrading from Q -> R will only have the softap.conf file.
+ // Test devices running previous R builds however may have already migrated to the
+ // XML format. So, check for that above before falling back to check for legacy file.
+ if (storeFileId == STORE_FILE_SHARED_SOFTAP) {
+ return SoftApConfToXmlMigrationUtil.convert();
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Remove the legacy shared wifi config store file.
+ *
+ * @param storeFileId Identifier for the config store file. One of
+ * {@link #STORE_FILE_SHARED_GENERAL} or {@link #STORE_FILE_SHARED_GENERAL}
+ * @throws IllegalArgumentException on invalid storeFileId.
+ */
+ public static void removeSharedConfigStoreFile(@SharedStoreFileId int storeFileId) {
+ if (storeFileId != STORE_FILE_SHARED_GENERAL && storeFileId != STORE_FILE_SHARED_SOFTAP) {
+ throw new IllegalArgumentException("Invalid shared store file id");
+ }
+ AtomicFile file = getSharedAtomicFile(storeFileId);
+ if (file.exists()) {
+ file.delete();
+ return;
+ }
+ // Special handling for softap.conf.
+ // Note: OEM devices upgrading from Q -> R will only have the softap.conf file.
+ // Test devices running previous R builds however may have already migrated to the
+ // XML format. So, check for that above before falling back to check for legacy file.
+ if (storeFileId == STORE_FILE_SHARED_SOFTAP) {
+ SoftApConfToXmlMigrationUtil.remove();
+ }
+ }
+
+ /**
+ * Load data from legacy user wifi config store file.
+ * TODO(b/149418926): Add XSD for the AOSP file format for each file from R.
+ * <p>
+ * Note:
+ * <li>OEMs need to change the implementation of
+ * {@link #convertAndRetrieveUserConfigStoreFile(int, UserHandle)} only if their existing config
+ * store format or file locations differs from the vanilla AOSP implementation.</li>
+ * <li>The wifi apex will invoke
+ * {@link #convertAndRetrieveUserConfigStoreFile(int, UserHandle)}
+ * method on every bootup, it is the responsibility of the OEM implementation to ensure that
+ * they perform the necessary in place conversion of their config store file to conform to the
+ * AOSP format. The OEM should ensure that the method should only return the
+ * {@link InputStream} stream for the data to be migrated only on the first bootup.</li>
+ * <li>Once the migration is done, the apex will invoke
+ * {@link #removeUserConfigStoreFile(int, UserHandle)} to delete the store file.</li>
+ * <li>The only relevant invocation of
+ * {@link #convertAndRetrieveUserConfigStoreFile(int, UserHandle)} occurs when a previously
+ * released device upgrades to the wifi apex from an OEM implementation of the wifi
+ * stack.
+ * </li>
+ * <li>Ensure that the legacy file paths are accessible to the wifi module (sepolicy rules, file
+ * permissions, etc). Since the wifi service continues to run inside system_server process, this
+ * method will be called from the same context (so ideally the file should still be accessible).
+ * </li>
+ *
+ * @param storeFileId Identifier for the config store file. One of
+ * {@link #STORE_FILE_USER_GENERAL} or {@link #STORE_FILE_USER_NETWORK_SUGGESTIONS}
+ * @param userHandle User handle.
+ * @return Instance of {@link InputStream} for migrating data, null if no migration is
+ * necessary.
+ * @throws IllegalArgumentException on invalid storeFileId or userHandle.
+ */
+ @Nullable
+ public static InputStream convertAndRetrieveUserConfigStoreFile(
+ @UserStoreFileId int storeFileId, @NonNull UserHandle userHandle) {
+ if (storeFileId != STORE_FILE_USER_GENERAL
+ && storeFileId != STORE_FILE_USER_NETWORK_SUGGESTIONS) {
+ throw new IllegalArgumentException("Invalid user store file id");
+ }
+ Objects.requireNonNull(userHandle);
+ try {
+ // OEMs should do conversions necessary here before returning the stream.
+ return getUserAtomicFile(storeFileId, userHandle.getIdentifier()).openRead();
+ } catch (FileNotFoundException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Remove the legacy user wifi config store file.
+ *
+ * @param storeFileId Identifier for the config store file. One of
+ * {@link #STORE_FILE_USER_GENERAL} or {@link #STORE_FILE_USER_NETWORK_SUGGESTIONS}
+ * @param userHandle User handle.
+ * @throws IllegalArgumentException on invalid storeFileId or userHandle.
+ */
+ public static void removeUserConfigStoreFile(
+ @UserStoreFileId int storeFileId, @NonNull UserHandle userHandle) {
+ if (storeFileId != STORE_FILE_USER_GENERAL
+ && storeFileId != STORE_FILE_USER_NETWORK_SUGGESTIONS) {
+ throw new IllegalArgumentException("Invalid user store file id");
+ }
+ Objects.requireNonNull(userHandle);
+ AtomicFile file = getUserAtomicFile(storeFileId, userHandle.getIdentifier());
+ if (file.exists()) {
+ file.delete();
+ }
+ }
+
+ /**
* Container for all the wifi settings data to migrate.
*/
public static final class SettingsMigrationData implements Parcelable {
@@ -260,7 +508,7 @@
* <li> This is method is invoked once on the first bootup. OEM can safely delete these settings
* once the migration is complete. The first & only relevant invocation of
* {@link #loadFromSettings(Context)} ()} occurs when a previously released
- * device upgrades to the wifi mainline module from an OEM implementation of the wifi stack.
+ * device upgrades to the wifi apex from an OEM implementation of the wifi stack.
* </li>
*
* @param context Context to use for loading the settings provider.
diff --git a/wifi/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java b/wifi/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java
new file mode 100644
index 0000000..f49f387
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java
@@ -0,0 +1,199 @@
+/*
+ * 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.net.wifi;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Unit tests for {@link android.net.wifi.SoftApConfToXmlMigrationUtilTest}.
+ */
+@SmallTest
+public class SoftApConfToXmlMigrationUtilTest {
+ private static final String TEST_SSID = "SSID";
+ private static final String TEST_PASSPHRASE = "TestPassphrase";
+ private static final int TEST_CHANNEL = 0;
+ private static final boolean TEST_HIDDEN = false;
+ private static final int TEST_BAND = SoftApConfiguration.BAND_5GHZ;
+ private static final int TEST_SECURITY = SoftApConfiguration.SECURITY_TYPE_WPA2_PSK;
+
+ private static final String TEST_EXPECTED_XML_STRING =
+ "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<WifiConfigStoreData>\n"
+ + "<int name=\"Version\" value=\"3\" />\n"
+ + "<SoftAp>\n"
+ + "<string name=\"SSID\">" + TEST_SSID + "</string>\n"
+ + "<int name=\"ApBand\" value=\"" + TEST_BAND + "\" />\n"
+ + "<int name=\"Channel\" value=\"" + TEST_CHANNEL + "\" />\n"
+ + "<boolean name=\"HiddenSSID\" value=\"" + TEST_HIDDEN + "\" />\n"
+ + "<int name=\"SecurityType\" value=\"" + TEST_SECURITY + "\" />\n"
+ + "<string name=\"Passphrase\">" + TEST_PASSPHRASE + "</string>\n"
+ + "<int name=\"MaxNumberOfClients\" value=\"0\" />\n"
+ + "<boolean name=\"ClientControlByUser\" value=\"false\" />\n"
+ + "<boolean name=\"AutoShutdownEnabled\" value=\"true\" />\n"
+ + "<long name=\"ShutdownTimeoutMillis\" value=\"0\" />\n"
+ + "<BlockedClientList />\n"
+ + "<AllowedClientList />\n"
+ + "</SoftAp>\n"
+ + "</WifiConfigStoreData>\n";
+
+ private byte[] createLegacyApConfFile(WifiConfiguration config) throws Exception {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(outputStream);
+ out.writeInt(3);
+ out.writeUTF(config.SSID);
+ out.writeInt(config.apBand);
+ out.writeInt(config.apChannel);
+ out.writeBoolean(config.hiddenSSID);
+ int authType = config.getAuthType();
+ out.writeInt(authType);
+ if (authType != WifiConfiguration.KeyMgmt.NONE) {
+ out.writeUTF(config.preSharedKey);
+ }
+ out.close();
+ return outputStream.toByteArray();
+ }
+
+ /**
+ * Generate a SoftApConfiguration based on the specified parameters.
+ */
+ private SoftApConfiguration setupApConfig(
+ String ssid, String preSharedKey, int keyManagement, int band, int channel,
+ boolean hiddenSSID) {
+ SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
+ configBuilder.setSsid(ssid);
+ configBuilder.setPassphrase(preSharedKey, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+ if (channel == 0) {
+ configBuilder.setBand(band);
+ } else {
+ configBuilder.setChannel(channel, band);
+ }
+ configBuilder.setHiddenSsid(hiddenSSID);
+ return configBuilder.build();
+ }
+
+ /**
+ * Generate a WifiConfiguration based on the specified parameters.
+ */
+ private WifiConfiguration setupWifiConfigurationApConfig(
+ String ssid, String preSharedKey, int keyManagement, int band, int channel,
+ boolean hiddenSSID) {
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = ssid;
+ config.preSharedKey = preSharedKey;
+ config.allowedKeyManagement.set(keyManagement);
+ config.apBand = band;
+ config.apChannel = channel;
+ config.hiddenSSID = hiddenSSID;
+ return config;
+ }
+
+ /**
+ * Asserts that the WifiConfigurations equal to SoftApConfiguration.
+ * This only compares the elements saved
+ * for softAp used.
+ */
+ public static void assertWifiConfigurationEqualSoftApConfiguration(
+ WifiConfiguration backup, SoftApConfiguration restore) {
+ assertEquals(backup.SSID, restore.getSsid());
+ assertEquals(backup.BSSID, restore.getBssid());
+ assertEquals(SoftApConfToXmlMigrationUtil.convertWifiConfigBandToSoftApConfigBand(
+ backup.apBand),
+ restore.getBand());
+ assertEquals(backup.apChannel, restore.getChannel());
+ assertEquals(backup.preSharedKey, restore.getPassphrase());
+ if (backup.getAuthType() == WifiConfiguration.KeyMgmt.WPA2_PSK) {
+ assertEquals(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK, restore.getSecurityType());
+ } else {
+ assertEquals(SoftApConfiguration.SECURITY_TYPE_OPEN, restore.getSecurityType());
+ }
+ assertEquals(backup.hiddenSSID, restore.isHiddenSsid());
+ }
+
+ /**
+ * Note: This is a copy of {@link AtomicFile#readFully()} modified to use the passed in
+ * {@link InputStream} which was returned using {@link AtomicFile#openRead()}.
+ */
+ private static byte[] readFully(InputStream stream) throws IOException {
+ try {
+ int pos = 0;
+ int avail = stream.available();
+ byte[] data = new byte[avail];
+ while (true) {
+ int amt = stream.read(data, pos, data.length - pos);
+ if (amt <= 0) {
+ return data;
+ }
+ pos += amt;
+ avail = stream.available();
+ if (avail > data.length - pos) {
+ byte[] newData = new byte[pos + avail];
+ System.arraycopy(data, 0, newData, 0, pos);
+ data = newData;
+ }
+ }
+ } finally {
+ stream.close();
+ }
+ }
+
+ /**
+ * Tests conversion from legacy .conf file to XML file format.
+ */
+ @Test
+ public void testConversion() throws Exception {
+ WifiConfiguration backupConfig = setupWifiConfigurationApConfig(
+ TEST_SSID, /* SSID */
+ TEST_PASSPHRASE, /* preshared key */
+ WifiConfiguration.KeyMgmt.WPA2_PSK, /* key management */
+ 1, /* AP band (5GHz) */
+ TEST_CHANNEL, /* AP channel */
+ TEST_HIDDEN /* Hidden SSID */);
+ SoftApConfiguration expectedConfig = setupApConfig(
+ TEST_SSID, /* SSID */
+ TEST_PASSPHRASE, /* preshared key */
+ SoftApConfiguration.SECURITY_TYPE_WPA2_PSK, /* security type */
+ SoftApConfiguration.BAND_5GHZ, /* AP band (5GHz) */
+ TEST_CHANNEL, /* AP channel */
+ TEST_HIDDEN /* Hidden SSID */);
+
+ assertWifiConfigurationEqualSoftApConfiguration(backupConfig, expectedConfig);
+
+ byte[] confBytes = createLegacyApConfFile(backupConfig);
+ assertNotNull(confBytes);
+
+ InputStream xmlStream = SoftApConfToXmlMigrationUtil.convert(
+ new ByteArrayInputStream(confBytes));
+
+ byte[] xmlBytes = readFully(xmlStream);
+ assertNotNull(xmlBytes);
+
+ assertEquals(TEST_EXPECTED_XML_STRING, new String(xmlBytes));
+ }
+
+}