Merge "Fix NPE with disabled overflow." into rvc-dev
diff --git a/Android.bp b/Android.bp
index 71513b7..53417e8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -281,17 +281,33 @@
filegroup {
name: "framework-updatable-sources",
srcs: [
- ":framework-sdkextensions-sources",
- ":framework-statsd-sources",
- ":framework-tethering-srcs",
- ":updatable-media-srcs",
":framework-mediaprovider-sources",
":framework-permission-sources",
- ":framework-wifi-updatable-sources",
+ ":framework-sdkextensions-sources",
+ ":framework-statsd-sources",
":framework-telephony-sources",
+ ":framework-tethering-srcs",
+ ":framework-wifi-updatable-sources",
+ ":updatable-media-srcs",
]
}
+java_library {
+ name: "framework-updatable-stubs-module_libs_api",
+ static_libs: [
+ "framework-media-stubs-module_libs_api",
+ "framework-mediaprovider-stubs-module_libs_api",
+ "framework-permission-stubs-module_libs_api",
+ "framework-sdkextensions-stubs-module_libs_api",
+ "framework-statsd-stubs-module_libs_api",
+ "framework-telephony-stubs", // TODO: Update to module_libs_api when there is one.
+ "framework-tethering-stubs-module_libs_api",
+ "framework-wifi-stubs-module_libs_api",
+ ],
+ sdk_version: "module_current",
+ visibility: [":__pkg__"],
+}
+
filegroup {
name: "framework-all-sources",
srcs: [
@@ -307,7 +323,6 @@
name: "framework-aidl-export-defaults",
aidl: {
export_include_dirs: [
- "apex/media/framework/java",
"core/java",
"drm/java",
"graphics/java",
@@ -324,6 +339,12 @@
"rs/java",
"sax/java",
"telecomm/java",
+
+ // TODO(b/148660295): remove this
+ "apex/media/framework/java",
+
+ // TODO(b/147699819): remove this
+ "telephony/java",
],
},
}
@@ -397,9 +418,7 @@
"app-compat-annotations",
"ext",
"unsupportedappusage",
- "framework-media-stubs-systemapi",
- "framework-mediaprovider-stubs-systemapi",
- "framework-telephony-stubs",
+ "framework-updatable-stubs-module_libs_api",
],
jarjar_rules: ":framework-jarjar-rules",
@@ -465,13 +484,6 @@
name: "framework-minus-apex",
defaults: ["framework-defaults"],
srcs: [":framework-non-updatable-sources"],
- libs: [
- "framework-sdkextensions-stubs-systemapi",
- "framework-statsd-stubs-module_libs_api",
- "framework-permission-stubs-systemapi",
- "framework-wifi-stubs-systemapi",
- "framework-tethering-stubs-module_libs_api",
- ],
installable: true,
javac_shard_size: 150,
required: [
@@ -512,16 +524,9 @@
installable: false, // this lib is a build-only library
static_libs: [
"framework-minus-apex",
- "framework-media-stubs-systemapi",
- "framework-mediaprovider-stubs-systemapi",
- "framework-permission-stubs-systemapi",
- "framework-sdkextensions-stubs-systemapi",
- "framework-statsd-stubs-module_libs_api",
- "framework-wifi-stubs-systemapi",
- "framework-tethering-stubs-module_libs_api",
- // TODO (b/147688669) should be framework-telephony-stubs
+ // TODO (b/147688669) should be removed
"framework-telephony",
- // TODO(jiyong): add stubs for APEXes here
+ "framework-updatable-stubs-module_libs_api",
],
sdk_version: "core_platform",
apex_available: ["//apex_available:platform"],
@@ -541,7 +546,6 @@
// DO NOT ADD ANY MORE ENTRIES TO THIS LIST
"//external/robolectric-shadows:__subpackages__",
"//frameworks/layoutlib:__subpackages__",
- "//frameworks/opt/net/ike:__subpackages__",
],
}
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index c458d11..e042782 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -670,7 +670,7 @@
private void startApp(int userId, String packageName) throws RemoteException {
final Context context = InstrumentationRegistry.getContext();
final WaitResult result = ActivityTaskManager.getService().startActivityAndWait(null,
- context.getPackageName(), context.getFeatureId(),
+ context.getPackageName(), context.getAttributionTag(),
context.getPackageManager().getLaunchIntentForPackage(packageName), null, null,
null, 0, 0, null, null, userId);
attestTrue("User " + userId + " failed to start " + packageName,
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index b905273..ae8976a 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -53,9 +53,8 @@
* Container of data passed to the {@link android.app.job.JobScheduler} fully encapsulating the
* parameters required to schedule work against the calling application. These are constructed
* using the {@link JobInfo.Builder}.
- * You must specify at least one sort of constraint on the JobInfo object that you are creating.
* The goal here is to provide the scheduler with high-level semantics about the work you want to
- * accomplish. Doing otherwise with throw an exception in your app.
+ * accomplish.
*/
public class JobInfo implements Parcelable {
private static String TAG = "JobInfo";
@@ -147,7 +146,7 @@
/**
* Query the minimum interval allowed for periodic scheduled jobs. Attempting
- * to declare a smaller period that this when scheduling a job will result in a
+ * to declare a smaller period than this when scheduling a job will result in a
* job that is still periodic, but will run with this effective period.
*
* @return The minimum available interval for scheduling periodic jobs, in milliseconds.
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index b219fd41..29c48ad 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -139,7 +139,7 @@
* @Override
* public void onSampleCompleted(
* int trackIndex,
- * long timeUs,
+ * long timeMicros,
* int flags,
* int size,
* int offset,
@@ -163,7 +163,7 @@
* /* destPos= */ 0,
* /* size= */ offset);
* bytesWrittenCount = bytesWrittenCount - offset;
- * publishSample(sampleData, timeUs, flags);
+ * publishSample(sampleData, timeMicros, flags);
* }
*
* private void ensureSpaceInBuffer(int numberOfBytesToRead) {
@@ -187,7 +187,7 @@
*/
public static final class SeekMap {
- /** Returned by {@link #getDurationUs()} when the duration is unknown. */
+ /** Returned by {@link #getDurationMicros()} when the duration is unknown. */
public static final int UNKNOWN_DURATION = Integer.MIN_VALUE;
private final com.google.android.exoplayer2.extractor.SeekMap mExoPlayerSeekMap;
@@ -205,26 +205,26 @@
* Returns the duration of the stream in microseconds or {@link #UNKNOWN_DURATION} if the
* duration is unknown.
*/
- public long getDurationUs() {
+ public long getDurationMicros() {
return mExoPlayerSeekMap.getDurationUs();
}
/**
* Obtains {@link SeekPoint SeekPoints} for the specified seek time in microseconds.
*
- * <p>{@code getSeekPoints(timeUs).first} contains the latest seek point for samples with
- * timestamp equal to or smaller than {@code timeUs}.
+ * <p>{@code getSeekPoints(timeMicros).first} contains the latest seek point for samples
+ * with timestamp equal to or smaller than {@code timeMicros}.
*
- * <p>{@code getSeekPoints(timeUs).second} contains the earliest seek point for samples with
- * timestamp equal to or greater than {@code timeUs}. If a seek point exists for {@code
- * timeUs}, the returned pair will contain the same {@link SeekPoint} twice.
+ * <p>{@code getSeekPoints(timeMicros).second} contains the earliest seek point for samples
+ * with timestamp equal to or greater than {@code timeMicros}. If a seek point exists for
+ * {@code timeMicros}, the returned pair will contain the same {@link SeekPoint} twice.
*
- * @param timeUs A seek time in microseconds.
+ * @param timeMicros A seek time in microseconds.
* @return The corresponding {@link SeekPoint SeekPoints}.
*/
@NonNull
- public Pair<SeekPoint, SeekPoint> getSeekPoints(long timeUs) {
- SeekPoints seekPoints = mExoPlayerSeekMap.getSeekPoints(timeUs);
+ public Pair<SeekPoint, SeekPoint> getSeekPoints(long timeMicros) {
+ SeekPoints seekPoints = mExoPlayerSeekMap.getSeekPoints(timeMicros);
return new Pair<>(toSeekPoint(seekPoints.first), toSeekPoint(seekPoints.second));
}
}
@@ -254,24 +254,24 @@
@NonNull public static final SeekPoint START = new SeekPoint(0, 0);
/** The time of the seek point, in microseconds. */
- public final long timeUs;
+ public final long timeMicros;
/** The byte offset of the seek point. */
public final long position;
/**
- * @param timeUs The time of the seek point, in microseconds.
+ * @param timeMicros The time of the seek point, in microseconds.
* @param position The byte offset of the seek point.
*/
- private SeekPoint(long timeUs, long position) {
- this.timeUs = timeUs;
+ private SeekPoint(long timeMicros, long position) {
+ this.timeMicros = timeMicros;
this.position = position;
}
@Override
@NonNull
public String toString() {
- return "[timeUs=" + timeUs + ", position=" + position + "]";
+ return "[timeMicros=" + timeMicros + ", position=" + position + "]";
}
@Override
@@ -283,12 +283,12 @@
return false;
}
SeekPoint other = (SeekPoint) obj;
- return timeUs == other.timeUs && position == other.position;
+ return timeMicros == other.timeMicros && position == other.position;
}
@Override
public int hashCode() {
- int result = (int) timeUs;
+ int result = (int) timeMicros;
result = 31 * result + (int) position;
return result;
}
@@ -345,25 +345,25 @@
*
* @param seekMap The extracted {@link SeekMap}.
*/
- void onSeekMap(@NonNull SeekMap seekMap);
+ void onSeekMapFound(@NonNull SeekMap seekMap);
/**
* Called when the number of tracks is found.
*
* @param numberOfTracks The number of tracks in the stream.
*/
- void onTracksFound(int numberOfTracks);
+ void onTrackCountFound(int numberOfTracks);
/**
- * Called when new {@link TrackData} is extracted from the stream.
+ * Called when new {@link TrackData} is found in the stream.
*
* @param trackIndex The index of the track for which the {@link TrackData} was extracted.
* @param trackData The extracted {@link TrackData}.
*/
- void onTrackData(int trackIndex, @NonNull TrackData trackData);
+ void onTrackDataFound(int trackIndex, @NonNull TrackData trackData);
/**
- * Called to write sample data to the output.
+ * Called when sample data is found in the stream.
*
* <p>If the invocation of this method returns before the entire {@code inputReader} {@link
* InputReader#getLength() length} is consumed, the method will be called again for the
@@ -374,15 +374,15 @@
* @param inputReader The {@link InputReader} from which to read the data.
* @throws IOException If an exception occurs while reading from {@code inputReader}.
*/
- void onSampleData(int trackIndex, @NonNull InputReader inputReader) throws IOException;
+ void onSampleDataFound(int trackIndex, @NonNull InputReader inputReader) throws IOException;
/**
- * Called once all the data of a sample has been passed to {@link #onSampleData}.
+ * Called once all the data of a sample has been passed to {@link #onSampleDataFound}.
*
* <p>Also includes sample metadata, like presentation timestamp and flags.
*
* @param trackIndex The index of the track to which the sample corresponds.
- * @param timeUs The media timestamp associated with the sample, in microseconds.
+ * @param timeMicros The media timestamp associated with the sample, in microseconds.
* @param flags Flags associated with the sample. See {@link MediaCodec
* MediaCodec.BUFFER_FLAG_*}.
* @param size The size of the sample data, in bytes.
@@ -394,7 +394,7 @@
*/
void onSampleCompleted(
int trackIndex,
- long timeUs,
+ long timeMicros,
int flags,
int size,
int offset,
@@ -632,7 +632,7 @@
private Extractor mExtractor;
private ExtractorInput mExtractorInput;
private long mPendingSeekPosition;
- private long mPendingSeekTimeUs;
+ private long mPendingSeekTimeMicros;
// Public methods.
@@ -760,7 +760,7 @@
}
if (isPendingSeek()) {
- mExtractor.seek(mPendingSeekPosition, mPendingSeekTimeUs);
+ mExtractor.seek(mPendingSeekPosition, mPendingSeekTimeMicros);
removePendingSeek();
}
@@ -786,7 +786,7 @@
* Seeks within the media container being extracted.
*
* <p>{@link SeekPoint SeekPoints} can be obtained from the {@link SeekMap} passed to {@link
- * OutputConsumer#onSeekMap(SeekMap)}.
+ * OutputConsumer#onSeekMapFound(SeekMap)}.
*
* <p>Following a call to this method, the {@link InputReader} passed to the next invocation of
* {@link #advance} must provide data starting from {@link SeekPoint#position} in the stream.
@@ -796,9 +796,9 @@
public void seek(@NonNull SeekPoint seekPoint) {
if (mExtractor == null) {
mPendingSeekPosition = seekPoint.position;
- mPendingSeekTimeUs = seekPoint.timeUs;
+ mPendingSeekTimeMicros = seekPoint.timeMicros;
} else {
- mExtractor.seek(seekPoint.position, seekPoint.timeUs);
+ mExtractor.seek(seekPoint.position, seekPoint.timeMicros);
}
}
@@ -836,7 +836,7 @@
private void removePendingSeek() {
mPendingSeekPosition = -1;
- mPendingSeekTimeUs = -1;
+ mPendingSeekTimeMicros = -1;
}
// Private classes.
@@ -897,12 +897,12 @@
@Override
public void endTracks() {
- mOutputConsumer.onTracksFound(mTrackOutputAdapters.size());
+ mOutputConsumer.onTrackCountFound(mTrackOutputAdapters.size());
}
@Override
public void seekMap(com.google.android.exoplayer2.extractor.SeekMap exoplayerSeekMap) {
- mOutputConsumer.onSeekMap(new SeekMap(exoplayerSeekMap));
+ mOutputConsumer.onSeekMapFound(new SeekMap(exoplayerSeekMap));
}
}
@@ -916,7 +916,7 @@
@Override
public void format(Format format) {
- mOutputConsumer.onTrackData(
+ mOutputConsumer.onTrackDataFound(
mTrackIndex,
new TrackData(
toMediaFormat(format), toFrameworkDrmInitData(format.drmInitData)));
@@ -927,7 +927,7 @@
throws IOException {
mScratchExtractorInputAdapter.setExtractorInput(input, length);
long positionBeforeReading = mScratchExtractorInputAdapter.getPosition();
- mOutputConsumer.onSampleData(mTrackIndex, mScratchExtractorInputAdapter);
+ mOutputConsumer.onSampleDataFound(mTrackIndex, mScratchExtractorInputAdapter);
return (int) (mScratchExtractorInputAdapter.getPosition() - positionBeforeReading);
}
@@ -935,7 +935,7 @@
public void sampleData(ParsableByteArray data, int length) {
mScratchParsableByteArrayAdapter.resetWithByteArray(data, length);
try {
- mOutputConsumer.onSampleData(mTrackIndex, mScratchParsableByteArrayAdapter);
+ mOutputConsumer.onSampleDataFound(mTrackIndex, mScratchParsableByteArrayAdapter);
} catch (IOException e) {
// Unexpected.
throw new RuntimeException(e);
diff --git a/api/current.txt b/api/current.txt
index d944d24..0e46cea 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -572,6 +572,7 @@
field public static final int elevation = 16843840; // 0x1010440
field public static final int ellipsize = 16842923; // 0x10100ab
field public static final int ems = 16843096; // 0x1010158
+ field public static final int enableGwpAsan = 16844310; // 0x1010616
field public static final int enableVrMode = 16844069; // 0x1010525
field public static final int enabled = 16842766; // 0x101000e
field public static final int end = 16843996; // 0x10104dc
@@ -620,7 +621,6 @@
field public static final int fastScrollTextColor = 16843609; // 0x1010359
field public static final int fastScrollThumbDrawable = 16843574; // 0x1010336
field public static final int fastScrollTrackDrawable = 16843577; // 0x1010339
- field public static final int featureId = 16844301; // 0x101060d
field public static final int fillAfter = 16843197; // 0x10101bd
field public static final int fillAlpha = 16843980; // 0x10104cc
field public static final int fillBefore = 16843196; // 0x10101bc
@@ -4586,7 +4586,7 @@
public final class AsyncNotedAppOp implements android.os.Parcelable {
method public int describeContents();
- method @Nullable public String getFeatureId();
+ method @Nullable public String getAttributionTag();
method @NonNull public String getMessage();
method @IntRange(from=0) public int getNotingUid();
method @NonNull public String getOp();
@@ -6430,7 +6430,7 @@
public final class SyncNotedAppOp implements android.os.Parcelable {
ctor public SyncNotedAppOp(@IntRange(from=0L) int, @Nullable String);
method public int describeContents();
- method @Nullable public String getFeatureId();
+ method @Nullable public String getAttributionTag();
method @NonNull public String getOp();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.SyncNotedAppOp> CREATOR;
@@ -6856,9 +6856,9 @@
method @Nullable public String getAlwaysOnVpnPackage(@NonNull android.content.ComponentName);
method @NonNull @WorkerThread public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String);
method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName);
- method public boolean getAutoTime(@NonNull android.content.ComponentName);
+ method public boolean getAutoTimeEnabled(@NonNull android.content.ComponentName);
method @Deprecated public boolean getAutoTimeRequired();
- method public boolean getAutoTimeZone(@NonNull android.content.ComponentName);
+ method public boolean getAutoTimeZoneEnabled(@NonNull android.content.ComponentName);
method @NonNull public java.util.List<android.os.UserHandle> getBindDeviceAdminTargetUsers(@NonNull android.content.ComponentName);
method public boolean getBluetoothContactSharingDisabled(@NonNull android.content.ComponentName);
method public boolean getCameraDisabled(@Nullable android.content.ComponentName);
@@ -6982,9 +6982,9 @@
method public boolean setApplicationHidden(@NonNull android.content.ComponentName, String, boolean);
method @WorkerThread public void setApplicationRestrictions(@Nullable android.content.ComponentName, String, android.os.Bundle);
method @Deprecated public void setApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName, @Nullable String) throws android.content.pm.PackageManager.NameNotFoundException;
- method public void setAutoTime(@NonNull android.content.ComponentName, boolean);
+ method public void setAutoTimeEnabled(@NonNull android.content.ComponentName, boolean);
method @Deprecated public void setAutoTimeRequired(@NonNull android.content.ComponentName, boolean);
- method public void setAutoTimeZone(@NonNull android.content.ComponentName, boolean);
+ method public void setAutoTimeZoneEnabled(@NonNull android.content.ComponentName, boolean);
method public void setBackupServiceEnabled(@NonNull android.content.ComponentName, boolean);
method public void setBluetoothContactSharingDisabled(@NonNull android.content.ComponentName, boolean);
method public void setCameraDisabled(@NonNull android.content.ComponentName, boolean);
@@ -9696,7 +9696,7 @@
method public abstract int delete(@NonNull android.net.Uri, @Nullable String, @Nullable String[]);
method public int delete(@NonNull android.net.Uri, @Nullable android.os.Bundle);
method public void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
- method @Nullable public final String getCallingFeatureId();
+ method @Nullable public final String getCallingAttributionTag();
method @Nullable public final String getCallingPackage();
method @Nullable public final String getCallingPackageUnchecked();
method @Nullable public final android.content.Context getContext();
@@ -10030,11 +10030,11 @@
method @CheckResult(suggest="#enforceUriPermission(Uri,int,int,String)") public abstract int checkUriPermission(android.net.Uri, int, int, int);
method @CheckResult(suggest="#enforceUriPermission(Uri,String,String,int,int,int,String)") public abstract int checkUriPermission(@Nullable android.net.Uri, @Nullable String, @Nullable String, int, int, int);
method @Deprecated public abstract void clearWallpaper() throws java.io.IOException;
+ method @NonNull public android.content.Context createAttributionContext(@Nullable String);
method public abstract android.content.Context createConfigurationContext(@NonNull android.content.res.Configuration);
method public abstract android.content.Context createContextForSplit(String) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract android.content.Context createDeviceProtectedStorageContext();
method public abstract android.content.Context createDisplayContext(@NonNull android.view.Display);
- method @NonNull public android.content.Context createFeatureContext(@Nullable String);
method public abstract android.content.Context createPackageContext(String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.Context createWindowContext(int, @Nullable android.os.Bundle);
method public abstract String[] databaseList();
@@ -10052,6 +10052,7 @@
method public abstract android.content.Context getApplicationContext();
method public abstract android.content.pm.ApplicationInfo getApplicationInfo();
method public abstract android.content.res.AssetManager getAssets();
+ method @Nullable public String getAttributionTag();
method public abstract java.io.File getCacheDir();
method public abstract ClassLoader getClassLoader();
method public abstract java.io.File getCodeCacheDir();
@@ -10068,7 +10069,6 @@
method @Nullable public abstract java.io.File getExternalFilesDir(@Nullable String);
method public abstract java.io.File[] getExternalFilesDirs(String);
method @Deprecated public abstract java.io.File[] getExternalMediaDirs();
- method @Nullable public String getFeatureId();
method public abstract java.io.File getFileStreamPath(String);
method public abstract java.io.File getFilesDir();
method public java.util.concurrent.Executor getMainExecutor();
@@ -10806,6 +10806,7 @@
field public static final String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";
field public static final String EXTRA_TEXT = "android.intent.extra.TEXT";
field public static final String EXTRA_TIME = "android.intent.extra.TIME";
+ field public static final String EXTRA_TIMEZONE = "time-zone";
field public static final String EXTRA_TITLE = "android.intent.extra.TITLE";
field public static final String EXTRA_UID = "android.intent.extra.UID";
field public static final String EXTRA_USER = "android.intent.extra.USER";
@@ -11438,6 +11439,7 @@
method public int describeContents();
method public void dump(android.util.Printer, String);
method public static CharSequence getCategoryTitle(android.content.Context, int);
+ method @Nullable public Boolean isGwpAsanEnabled();
method public boolean isProfileableByShell();
method public boolean isResourceOverlay();
method public boolean isVirtualPreload();
@@ -11571,6 +11573,7 @@
method @NonNull public CharSequence getProfileSwitchingLabel(@NonNull android.os.UserHandle);
method @NonNull public java.util.List<android.os.UserHandle> getTargetUserProfiles();
method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, "android.permission.INTERACT_ACROSS_USERS"}) public void startActivity(@NonNull android.content.Intent, @NonNull android.os.UserHandle, @Nullable android.app.Activity);
+ method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, "android.permission.INTERACT_ACROSS_USERS"}) public void startActivity(@NonNull android.content.Intent, @NonNull android.os.UserHandle, @Nullable android.app.Activity, @Nullable android.os.Bundle);
method public void startMainActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
field public static final String ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED = "android.content.pm.action.CAN_INTERACT_ACROSS_PROFILES_CHANGED";
}
@@ -26448,14 +26451,14 @@
public static interface MediaParser.OutputConsumer {
method public void onSampleCompleted(int, long, int, int, int, @Nullable android.media.MediaCodec.CryptoInfo);
- method public void onSampleData(int, @NonNull android.media.MediaParser.InputReader) throws java.io.IOException;
- method public void onSeekMap(@NonNull android.media.MediaParser.SeekMap);
- method public void onTrackData(int, @NonNull android.media.MediaParser.TrackData);
- method public void onTracksFound(int);
+ 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.SeekMap {
- method public long getDurationUs();
+ 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
@@ -26464,7 +26467,7 @@
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 timeUs;
+ field public final long timeMicros;
}
public static interface MediaParser.SeekableInputReader extends android.media.MediaParser.InputReader {
@@ -45973,9 +45976,6 @@
field public static final int MISSED = 5; // 0x5
field public static final int OTHER = 9; // 0x9
field public static final String REASON_EMERGENCY_CALL_PLACED = "REASON_EMERGENCY_CALL_PLACED";
- field public static final String REASON_EMULATING_SINGLE_CALL = "EMULATING_SINGLE_CALL";
- field public static final String REASON_IMS_ACCESS_BLOCKED = "REASON_IMS_ACCESS_BLOCKED";
- field public static final String REASON_WIFI_ON_BUT_WFC_OFF = "REASON_WIFI_ON_BUT_WFC_OFF";
field public static final int REJECTED = 6; // 0x6
field public static final int REMOTE = 3; // 0x3
field public static final int RESTRICTED = 8; // 0x8
@@ -46302,7 +46302,6 @@
field public static final int DURATION_SHORT = 1; // 0x1
field public static final int DURATION_VERY_SHORT = 0; // 0x0
field public static final String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER";
- field public static final String EXTRA_CALL_CREATED_TIME_MILLIS = "android.telecom.extra.CALL_CREATED_TIME_MILLIS";
field public static final String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE";
field public static final String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE";
field public static final String EXTRA_CALL_DURATION = "android.telecom.extra.CALL_DURATION";
@@ -48044,13 +48043,13 @@
method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.os.ParcelUuid createSubscriptionGroup(@NonNull java.util.List<java.lang.Integer>);
method @Deprecated public static android.telephony.SubscriptionManager from(android.content.Context);
method public java.util.List<android.telephony.SubscriptionInfo> getAccessibleSubscriptionInfoList();
- method @Nullable public java.util.List<android.telephony.SubscriptionInfo> getActiveAndHiddenSubscriptionInfoList();
method public static int getActiveDataSubscriptionId();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfo(int);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getActiveSubscriptionInfoCount();
method public int getActiveSubscriptionInfoCountMax();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telephony.SubscriptionInfo> getActiveSubscriptionInfoList();
+ method @NonNull public java.util.List<android.telephony.SubscriptionInfo> getCompleteActiveSubscriptionInfoList();
method public static int getDefaultDataSubscriptionId();
method public static int getDefaultSmsSubscriptionId();
method public static int getDefaultSubscriptionId();
@@ -48213,6 +48212,7 @@
method public boolean isEmergencyNumber(@NonNull String);
method public boolean isHearingAidCompatibilitySupported();
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public boolean isManualNetworkSelectionAllowed();
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isModemEnabledForSlot(int);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int isMultiSimSupported();
method public boolean isNetworkRoaming();
method public boolean isRttSupported();
@@ -48326,7 +48326,6 @@
field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
field public static final int PHONE_TYPE_CDMA = 2; // 0x2
field public static final int PHONE_TYPE_GSM = 1; // 0x1
- field public static final int PHONE_TYPE_IMS = 5; // 0x5
field public static final int PHONE_TYPE_NONE = 0; // 0x0
field public static final int PHONE_TYPE_SIP = 3; // 0x3
field public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2; // 0x2
@@ -82233,3 +82232,4 @@
}
}
+
diff --git a/api/lint-baseline.txt b/api/lint-baseline.txt
index 569e838..83c78fe 100644
--- a/api/lint-baseline.txt
+++ b/api/lint-baseline.txt
@@ -15,6 +15,16 @@
ArrayReturn: android.content.ContentProviderOperation#resolveExtrasBackReferences(android.content.ContentProviderResult[], int) parameter #0:
+ArrayReturn: android.location.GnssAntennaInfo.SphericalCorrections#SphericalCorrections(double[][], double[][]) parameter #0:
+ Method parameter should be Collection<> (or subclass) instead of raw array; was `double[][]`
+ArrayReturn: android.location.GnssAntennaInfo.SphericalCorrections#SphericalCorrections(double[][], double[][]) parameter #1:
+ Method parameter should be Collection<> (or subclass) instead of raw array; was `double[][]`
+ArrayReturn: android.location.GnssAntennaInfo.SphericalCorrections#getCorrectionUncertaintiesArray():
+ Method should return Collection<> (or subclass) instead of raw array; was `double[][]`
+ArrayReturn: android.location.GnssAntennaInfo.SphericalCorrections#getCorrectionsArray():
+ Method should return Collection<> (or subclass) instead of raw array; was `double[][]`
+ArrayReturn: android.service.autofill.FillResponse.Builder#setAuthentication(android.view.autofill.AutofillId[], android.content.IntentSender, android.widget.RemoteViews, android.service.autofill.InlinePresentation) parameter #0:
+ Method parameter should be Collection<AutofillId> (or subclass) instead of raw array; was `android.view.autofill.AutofillId[]`
BroadcastBehavior: android.app.AlarmManager#ACTION_NEXT_ALARM_CLOCK_CHANGED:
@@ -453,8 +463,12 @@
+ExecutorRegistration: android.media.MediaRouter2#setOnGetControllerHintsListener(android.media.MediaRouter2.OnGetControllerHintsListener):
+ Registration methods should have overload that accepts delivery Executor: `setOnGetControllerHintsListener`
+
+
GenericException: android.content.res.loader.ResourcesProvider#finalize():
- Methods must not throw generic exceptions (`java.lang.Throwable`)
+
HiddenSuperclass: android.content.res.ColorStateList:
@@ -499,6 +513,30 @@
+IntentBuilderName: android.net.VpnManager#provisionVpnProfile(android.net.PlatformVpnProfile):
+ Methods creating an Intent should be named `create<Foo>Intent()`, was `provisionVpnProfile`
+
+
+KotlinOperator: android.media.AudioMetadata.Map#set(android.media.AudioMetadata.Key<T>, T):
+ Method can be invoked with an indexing operator from Kotlin: `set` (this is usually desirable; just make sure it makes sense for this type of object)
+KotlinOperator: android.media.AudioMetadata.ReadMap#get(android.media.AudioMetadata.Key<T>):
+ Method can be invoked with an indexing operator from Kotlin: `get` (this is usually desirable; just make sure it makes sense for this type of object)
+
+
+MethodNameUnits: android.media.MediaParser.SeekMap#getDurationMicros():
+ Returned time values are strongly encouraged to be in milliseconds unless you need the extra precision, was `getDurationMicros`
+
+
+MinMaxConstant: android.telephony.DataFailCause#MAX_ACCESS_PROBE:
+ If min/max could change in future, make them dynamic methods: android.telephony.DataFailCause#MAX_ACCESS_PROBE
+MinMaxConstant: android.telephony.DataFailCause#MAX_IPV4_CONNECTIONS:
+ If min/max could change in future, make them dynamic methods: android.telephony.DataFailCause#MAX_IPV4_CONNECTIONS
+MinMaxConstant: android.telephony.DataFailCause#MAX_IPV6_CONNECTIONS:
+ If min/max could change in future, make them dynamic methods: android.telephony.DataFailCause#MAX_IPV6_CONNECTIONS
+MinMaxConstant: android.telephony.DataFailCause#MAX_PPP_INACTIVITY_TIMER_EXPIRED:
+ If min/max could change in future, make them dynamic methods: android.telephony.DataFailCause#MAX_PPP_INACTIVITY_TIMER_EXPIRED
+
+
MissingNullability: android.app.AsyncNotedAppOp#equals(Object) parameter #0:
MissingNullability: android.app.AsyncNotedAppOp#writeToParcel(android.os.Parcel, int) parameter #0:
@@ -506,11 +544,11 @@
MissingNullability: android.app.SyncNotedAppOp#equals(Object) parameter #0:
MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#CHORASMIAN:
- Missing nullability on field `CHORASMIAN` in class `class android.icu.lang.UCharacter.UnicodeBlock`
+
MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G:
- Missing nullability on field `CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G` in class `class android.icu.lang.UCharacter.UnicodeBlock`
+
MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#DIVES_AKURU:
- Missing nullability on field `DIVES_AKURU` in class `class android.icu.lang.UCharacter.UnicodeBlock`
+
MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS:
MissingNullability: android.icu.lang.UCharacter.UnicodeBlock#ELYMAIC:
@@ -556,14 +594,39 @@
MissingNullability: android.icu.util.VersionInfo#UNICODE_12_1:
MissingNullability: android.icu.util.VersionInfo#UNICODE_13_0:
- Missing nullability on field `UNICODE_13_0` in class `class android.icu.util.VersionInfo`
+
MissingNullability: android.media.MediaMetadataRetriever#getFrameAtTime(long, int, android.media.MediaMetadataRetriever.BitmapParams):
MissingNullability: android.media.MediaMetadataRetriever#getScaledFrameAtTime(long, int, int, int, android.media.MediaMetadataRetriever.BitmapParams):
-
MissingNullability: java.time.chrono.JapaneseEra#REIWA:
- Missing nullability on field `REIWA` in class `class java.time.chrono.JapaneseEra`
+
+
+
+NotCloseable: android.media.MediaCodec.GraphicBlock:
+ Classes that release resources (finalize()) should implement AutoClosable and CloseGuard: class android.media.MediaCodec.GraphicBlock
+NotCloseable: android.media.MediaCodec.LinearBlock:
+ Classes that release resources (finalize()) should implement AutoClosable and CloseGuard: class android.media.MediaCodec.LinearBlock
+NotCloseable: android.media.MediaParser:
+ Classes that release resources (release()) should implement AutoClosable and CloseGuard: class android.media.MediaParser
+NotCloseable: android.media.MediaRouter2.RoutingController:
+ Classes that release resources (release()) should implement AutoClosable and CloseGuard: class android.media.MediaRouter2.RoutingController
+NotCloseable: android.util.CloseGuard:
+ Classes that release resources (close()) should implement AutoClosable and CloseGuard: class android.util.CloseGuard
+NotCloseable: android.view.SurfaceControlViewHost:
+ Classes that release resources (release()) should implement AutoClosable and CloseGuard: class android.view.SurfaceControlViewHost
+
+
+OnNameExpected: android.app.admin.DevicePolicyKeyguardService#dismiss():
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.service.controls.ControlsProviderService#createPublisherFor(java.util.List<java.lang.String>):
+ Methods implemented by developers should follow the on<Something> style, was `createPublisherFor`
+OnNameExpected: android.service.controls.ControlsProviderService#createPublisherForAllAvailable():
+ Methods implemented by developers should follow the on<Something> style, was `createPublisherForAllAvailable`
+OnNameExpected: android.service.controls.ControlsProviderService#createPublisherForSuggested():
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.service.controls.ControlsProviderService#performControlAction(String, android.service.controls.actions.ControlAction, java.util.function.Consumer<java.lang.Integer>):
+ Methods implemented by developers should follow the on<Something> style, was `performControlAction`
RequiresPermission: android.accounts.AccountManager#getAccountsByTypeAndFeatures(String, String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler):
@@ -1189,11 +1252,13 @@
SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, java.util.concurrent.Executor, android.location.LocationListener):
SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, java.util.concurrent.Executor, android.location.LocationListener):
+
-
+StreamFiles: android.content.res.loader.DirectoryAssetsProvider#DirectoryAssetsProvider(java.io.File):
+ Methods accepting `File` should also accept `FileDescriptor` or streams: constructor android.content.res.loader.DirectoryAssetsProvider(java.io.File)
StreamFiles: android.content.res.loader.DirectoryResourceLoader#DirectoryResourceLoader(java.io.File):
- Methods accepting `File` should also accept `FileDescriptor` or streams: constructor android.content.res.loader.DirectoryResourceLoader(java.io.File)
+
Todo: android.hardware.camera2.params.StreamConfigurationMap:
diff --git a/api/removed.txt b/api/removed.txt
index 8537b21..077c915 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -1,4 +1,12 @@
// Signature format: 2.0
+package android {
+
+ public static final class R.attr {
+ field public static final int featureId = 16844301; // 0x101060d
+ }
+
+}
+
package android.app {
public class ActivityManager {
@@ -69,11 +77,17 @@
package android.content {
+ public abstract class ContentProvider implements android.content.ComponentCallbacks2 {
+ method @Deprecated @Nullable public final String getCallingFeatureId();
+ }
+
public abstract class ContentResolver {
method @Deprecated public void notifyChange(@NonNull Iterable<android.net.Uri>, @Nullable android.database.ContentObserver, int);
}
public abstract class Context {
+ method @Deprecated @NonNull public android.content.Context createFeatureContext(@Nullable String);
+ method @Deprecated @Nullable public String getFeatureId();
method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
method public abstract java.io.File getSharedPreferencesPath(String);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 65251d7..8e1c0be 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -448,14 +448,37 @@
field public static final int UID_STATE_TOP = 200; // 0xc8
}
- public static final class AppOpsManager.HistoricalFeatureOps implements android.os.Parcelable {
+ public static final class AppOpsManager.AttributedHistoricalOps implements android.os.Parcelable {
method public int describeContents();
- method @Nullable public String getFeatureId();
method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String);
method @NonNull public android.app.AppOpsManager.HistoricalOp getOpAt(@IntRange(from=0) int);
method @IntRange(from=0) public int getOpCount();
+ method @Nullable public String getTag();
method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalFeatureOps> CREATOR;
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.AttributedHistoricalOps> CREATOR;
+ }
+
+ public static final class AppOpsManager.AttributedOpEntry implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getLastAccessBackgroundTime(int);
+ method public long getLastAccessForegroundTime(int);
+ method public long getLastAccessTime(int);
+ method public long getLastAccessTime(int, int, int);
+ method public long getLastBackgroundDuration(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastBackgroundProxyInfo(int);
+ method public long getLastDuration(int);
+ method public long getLastDuration(int, int, int);
+ method public long getLastForegroundDuration(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastForegroundProxyInfo(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int, int, int);
+ method public long getLastRejectBackgroundTime(int);
+ method public long getLastRejectForegroundTime(int);
+ method public long getLastRejectTime(int);
+ method public long getLastRejectTime(int, int, int);
+ method public boolean isRunning();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.AttributedOpEntry> CREATOR;
}
public static final class AppOpsManager.HistoricalOp implements android.os.Parcelable {
@@ -491,7 +514,7 @@
public static final class AppOpsManager.HistoricalOpsRequest.Builder {
ctor public AppOpsManager.HistoricalOpsRequest.Builder(long, long);
method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest build();
- method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setFeatureId(@Nullable String);
+ method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setAttributionTag(@Nullable String);
method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setFlags(int);
method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setOpNames(@Nullable java.util.List<java.lang.String>);
method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setPackageName(@Nullable String);
@@ -500,9 +523,9 @@
public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable {
method public int describeContents();
- method @IntRange(from=0) public int getFeatureCount();
- method @Nullable public android.app.AppOpsManager.HistoricalFeatureOps getFeatureOps(@NonNull String);
- method @NonNull public android.app.AppOpsManager.HistoricalFeatureOps getFeatureOpsAt(@IntRange(from=0) int);
+ method @Nullable public android.app.AppOpsManager.AttributedHistoricalOps getAttributedOps(@NonNull String);
+ method @NonNull public android.app.AppOpsManager.AttributedHistoricalOps getAttributedOpsAt(@IntRange(from=0) int);
+ method @IntRange(from=0) public int getAttributedOpsCount();
method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String);
method @NonNull public android.app.AppOpsManager.HistoricalOp getOpAt(@IntRange(from=0) int);
method @IntRange(from=0) public int getOpCount();
@@ -523,8 +546,8 @@
public static final class AppOpsManager.OpEntry implements android.os.Parcelable {
method public int describeContents();
+ method @NonNull public java.util.Map<java.lang.String,android.app.AppOpsManager.AttributedOpEntry> getAttributedOpEntries();
method @Deprecated public long getDuration();
- method @NonNull public java.util.Map<java.lang.String,android.app.AppOpsManager.OpFeatureEntry> getFeatures();
method public long getLastAccessBackgroundTime(int);
method public long getLastAccessForegroundTime(int);
method public long getLastAccessTime(int);
@@ -554,36 +577,13 @@
public static final class AppOpsManager.OpEventProxyInfo implements android.os.Parcelable {
method public int describeContents();
- method @Nullable public String getFeatureId();
+ method @Nullable public String getAttributionTag();
method @Nullable public String getPackageName();
method @IntRange(from=0) public int getUid();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEventProxyInfo> CREATOR;
}
- public static final class AppOpsManager.OpFeatureEntry implements android.os.Parcelable {
- method public int describeContents();
- method public long getLastAccessBackgroundTime(int);
- method public long getLastAccessForegroundTime(int);
- method public long getLastAccessTime(int);
- method public long getLastAccessTime(int, int, int);
- method public long getLastBackgroundDuration(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastBackgroundProxyInfo(int);
- method public long getLastDuration(int);
- method public long getLastDuration(int, int, int);
- method public long getLastForegroundDuration(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastForegroundProxyInfo(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int, int, int);
- method public long getLastRejectBackgroundTime(int);
- method public long getLastRejectForegroundTime(int);
- method public long getLastRejectTime(int);
- method public long getLastRejectTime(int, int, int);
- method public boolean isRunning();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpFeatureEntry> CREATOR;
- }
-
public static final class AppOpsManager.PackageOps implements android.os.Parcelable {
method public int describeContents();
method @NonNull public java.util.List<android.app.AppOpsManager.OpEntry> getOps();
@@ -688,7 +688,7 @@
public final class RuntimeAppOpAccessMessage implements android.os.Parcelable {
ctor public RuntimeAppOpAccessMessage(@IntRange(from=0L) int, @IntRange(from=0L) int, @NonNull String, @Nullable String, @NonNull String, int);
method public int describeContents();
- method @Nullable public String getFeatureId();
+ method @Nullable public String getAttributionTag();
method @NonNull public String getMessage();
method @NonNull public String getOp();
method @NonNull public String getPackageName();
@@ -5620,8 +5620,8 @@
method public int getConstellation();
method public int getGuardInterval();
method public int getHierarchy();
- method public int getHpCodeRate();
- method public int getLpCodeRate();
+ method public int getHighPriorityCodeRate();
+ method public int getLowPriorityCodeRate();
method public int getPlpGroupId();
method public int getPlpId();
method public int getPlpMode();
@@ -5649,20 +5649,20 @@
field public static final int CODERATE_8_9 = 512; // 0x200
field public static final int CODERATE_AUTO = 1; // 0x1
field public static final int CODERATE_UNDEFINED = 0; // 0x0
+ field public static final int CONSTELLATION_16QAM = 4; // 0x4
+ field public static final int CONSTELLATION_256QAM = 16; // 0x10
+ field public static final int CONSTELLATION_64QAM = 8; // 0x8
field public static final int CONSTELLATION_AUTO = 1; // 0x1
- field public static final int CONSTELLATION_CONSTELLATION_16QAM = 4; // 0x4
- field public static final int CONSTELLATION_CONSTELLATION_256QAM = 16; // 0x10
- field public static final int CONSTELLATION_CONSTELLATION_64QAM = 8; // 0x8
- field public static final int CONSTELLATION_CONSTELLATION_QPSK = 2; // 0x2
+ field public static final int CONSTELLATION_QPSK = 2; // 0x2
field public static final int CONSTELLATION_UNDEFINED = 0; // 0x0
+ field public static final int GUARD_INTERVAL_19_128 = 64; // 0x40
+ field public static final int GUARD_INTERVAL_19_256 = 128; // 0x80
+ field public static final int GUARD_INTERVAL_1_128 = 32; // 0x20
+ field public static final int GUARD_INTERVAL_1_16 = 4; // 0x4
+ field public static final int GUARD_INTERVAL_1_32 = 2; // 0x2
+ field public static final int GUARD_INTERVAL_1_4 = 16; // 0x10
+ field public static final int GUARD_INTERVAL_1_8 = 8; // 0x8
field public static final int GUARD_INTERVAL_AUTO = 1; // 0x1
- field public static final int GUARD_INTERVAL_INTERVAL_19_128 = 64; // 0x40
- field public static final int GUARD_INTERVAL_INTERVAL_19_256 = 128; // 0x80
- field public static final int GUARD_INTERVAL_INTERVAL_1_128 = 32; // 0x20
- field public static final int GUARD_INTERVAL_INTERVAL_1_16 = 4; // 0x4
- field public static final int GUARD_INTERVAL_INTERVAL_1_32 = 2; // 0x2
- field public static final int GUARD_INTERVAL_INTERVAL_1_4 = 16; // 0x10
- field public static final int GUARD_INTERVAL_INTERVAL_1_8 = 8; // 0x8
field public static final int GUARD_INTERVAL_UNDEFINED = 0; // 0x0
field public static final int HIERARCHY_1_INDEPTH = 64; // 0x40
field public static final int HIERARCHY_1_NATIVE = 4; // 0x4
@@ -5697,8 +5697,8 @@
method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setGuardInterval(int);
method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setHierarchy(int);
method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setHighPriority(boolean);
- method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setHpCodeRate(int);
- method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setLpCodeRate(int);
+ method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setHighPriorityCodeRate(int);
+ method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setLowPriorityCodeRate(int);
method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setMiso(boolean);
method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setPlpGroupId(int);
method @NonNull public android.media.tv.tuner.frontend.DvbtFrontendSettings.Builder setPlpId(int);
@@ -7158,7 +7158,7 @@
method @NonNull public java.util.List<android.net.MacAddress> getBlockedClientList();
method public int getChannel();
method public int getMaxNumberOfClients();
- method public int getShutdownTimeoutMillis();
+ method public long getShutdownTimeoutMillis();
method public boolean isAutoShutdownEnabled();
method public boolean isClientControlByUserEnabled();
method @Nullable public android.net.wifi.WifiConfiguration toWifiConfiguration();
@@ -7172,16 +7172,17 @@
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 enableClientControlByUser(boolean);
+ 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 setClientList(@NonNull java.util.List<android.net.MacAddress>, @NonNull java.util.List<android.net.MacAddress>);
+ 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) 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);
}
@@ -7242,7 +7243,6 @@
field @Deprecated public int numScorerOverride;
field @Deprecated public int numScorerOverrideAndSwitchedNetwork;
field @Deprecated public boolean requirePmf;
- field @Deprecated @Nullable public String saePasswordId;
field @Deprecated public boolean shared;
field @Deprecated public boolean useExternalScores;
}
@@ -8225,13 +8225,15 @@
field public static final String ACTION_UPDATE_CARRIER_PROVISIONING_URLS = "android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS";
field public static final String ACTION_UPDATE_CONVERSATION_ACTIONS = "android.intent.action.UPDATE_CONVERSATION_ACTIONS";
field public static final String ACTION_UPDATE_CT_LOGS = "android.intent.action.UPDATE_CT_LOGS";
- field public static final String ACTION_UPDATE_EMERGENCY_NUMBER_DB = "android.os.action.UPDATE_EMERGENCY_NUMBER_DB";
+ field @RequiresPermission("android.permission.UPDATE_CONFIG") public static final String ACTION_UPDATE_EMERGENCY_NUMBER_DB = "android.os.action.UPDATE_EMERGENCY_NUMBER_DB";
field public static final String ACTION_UPDATE_INTENT_FIREWALL = "android.intent.action.UPDATE_INTENT_FIREWALL";
field public static final String ACTION_UPDATE_LANG_ID = "android.intent.action.UPDATE_LANG_ID";
field public static final String ACTION_UPDATE_NETWORK_WATCHLIST = "android.intent.action.UPDATE_NETWORK_WATCHLIST";
field public static final String ACTION_UPDATE_PINS = "android.intent.action.UPDATE_PINS";
field public static final String ACTION_UPDATE_SMART_SELECTION = "android.intent.action.UPDATE_SMART_SELECTION";
field public static final String ACTION_UPDATE_SMS_SHORT_CODES = "android.intent.action.UPDATE_SMS_SHORT_CODES";
+ field public static final String EXTRA_REQUIRED_HASH = "android.os.extra.REQUIRED_HASH";
+ field public static final String EXTRA_VERSION = "android.os.extra.VERSION";
}
public class Environment {
@@ -9068,18 +9070,6 @@
package android.provider {
- public class BlockedNumberContract {
- field public static final String METHOD_NOTIFY_EMERGENCY_CONTACT = "notify_emergency_contact";
- field public static final String METHOD_SHOULD_SYSTEM_BLOCK_NUMBER = "should_system_block_number";
- field public static final String RES_BLOCK_STATUS = "block_status";
- field public static final int STATUS_BLOCKED_IN_LIST = 1; // 0x1
- field public static final int STATUS_BLOCKED_NOT_IN_CONTACTS = 5; // 0x5
- field public static final int STATUS_BLOCKED_PAYPHONE = 4; // 0x4
- field public static final int STATUS_BLOCKED_RESTRICTED = 2; // 0x2
- field public static final int STATUS_BLOCKED_UNKNOWN_NUMBER = 3; // 0x3
- field public static final int STATUS_NOT_BLOCKED = 0; // 0x0
- }
-
@Deprecated public static final class ContactsContract.MetadataSync implements android.provider.BaseColumns android.provider.ContactsContract.MetadataSyncColumns {
field @Deprecated public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_metadata";
field @Deprecated public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_metadata";
@@ -9970,7 +9960,7 @@
}
public static final class DataLoaderService.FileSystemConnector {
- method public void writeData(@NonNull String, long, long, @NonNull android.os.ParcelFileDescriptor) throws java.io.IOException;
+ method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void writeData(@NonNull String, long, long, @NonNull android.os.ParcelFileDescriptor) throws java.io.IOException;
}
}
@@ -10648,14 +10638,7 @@
}
public final class PhoneAccount implements android.os.Parcelable {
- field public static final int CAPABILITY_EMERGENCY_CALLS_ONLY = 128; // 0x80
- field public static final int CAPABILITY_EMERGENCY_PREFERRED = 8192; // 0x2000
- field public static final int CAPABILITY_EMERGENCY_VIDEO_CALLING = 512; // 0x200
field public static final int CAPABILITY_MULTI_USER = 32; // 0x20
- field public static final String EXTRA_ALWAYS_USE_VOIP_AUDIO_MODE = "android.telecom.extra.ALWAYS_USE_VOIP_AUDIO_MODE";
- field public static final String EXTRA_PLAY_CALL_RECORDING_TONE = "android.telecom.extra.PLAY_CALL_RECORDING_TONE";
- field public static final String EXTRA_SORT_ORDER = "android.telecom.extra.SORT_ORDER";
- field public static final String EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK = "android.telecom.extra.SUPPORTS_VIDEO_CALLING_FALLBACK";
}
public static class PhoneAccount.Builder {
@@ -10741,20 +10724,13 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall();
method @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 void setUserSelectedOutgoingPhoneAccount(@Nullable android.telecom.PhoneAccountHandle);
- field public static final String ACTION_CURRENT_TTY_MODE_CHANGED = "android.telecom.action.CURRENT_TTY_MODE_CHANGED";
- field public static final String ACTION_TTY_PREFERRED_MODE_CHANGED = "android.telecom.action.TTY_PREFERRED_MODE_CHANGED";
field public static final int CALL_SOURCE_EMERGENCY_DIALPAD = 1; // 0x1
field public static final int CALL_SOURCE_EMERGENCY_SHORTCUT = 2; // 0x2
field public static final int CALL_SOURCE_UNSPECIFIED = 0; // 0x0
field public static final String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT";
- field public static final String EXTRA_CALL_SOURCE = "android.telecom.extra.CALL_SOURCE";
- field public static final String EXTRA_CALL_TECHNOLOGY_TYPE = "android.telecom.extra.CALL_TECHNOLOGY_TYPE";
field public static final String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
field public static final String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
- field public static final String EXTRA_CURRENT_TTY_MODE = "android.telecom.extra.CURRENT_TTY_MODE";
field public static final String EXTRA_IS_USER_INTENT_EMERGENCY_CALL = "android.telecom.extra.IS_USER_INTENT_EMERGENCY_CALL";
- field public static final String EXTRA_TTY_PREFERRED_MODE = "android.telecom.extra.TTY_PREFERRED_MODE";
- field public static final String EXTRA_UNKNOWN_CALL_HANDLE = "android.telecom.extra.UNKNOWN_CALL_HANDLE";
field public static final int TTY_MODE_FULL = 1; // 0x1
field public static final int TTY_MODE_HCO = 2; // 0x2
field public static final int TTY_MODE_OFF = 0; // 0x0
@@ -11332,7 +11308,6 @@
public class ServiceState implements android.os.Parcelable {
method public void fillInNotifierBundle(@NonNull android.os.Bundle);
method public int getDataNetworkType();
- method public int getDataRegistrationState();
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);
@@ -11599,11 +11574,10 @@
method @Deprecated public boolean getDataEnabled();
method @Deprecated public boolean getDataEnabled(int);
method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean);
- method @NonNull public static String getDefaultSimCountryIso();
method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
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 public int getEmergencyNumberDbVersion();
+ 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[] getIsimImpu();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
@@ -11633,7 +11607,7 @@
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 isDataAllowedInVoiceCall();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isDataConnectionEnabled();
+ 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();
@@ -11641,7 +11615,6 @@
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 public boolean isModemEnabledForSlot(int);
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);
@@ -11788,7 +11761,6 @@
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 PHONE_TYPE_THIRD_PARTY = 4; // 0x4
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
diff --git a/api/test-current.txt b/api/test-current.txt
index 218b934..9045646 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -263,14 +263,37 @@
field public static final int UID_STATE_TOP = 200; // 0xc8
}
- public static final class AppOpsManager.HistoricalFeatureOps implements android.os.Parcelable {
+ public static final class AppOpsManager.AttributedHistoricalOps implements android.os.Parcelable {
method public int describeContents();
- method @Nullable public String getFeatureId();
method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String);
method @NonNull public android.app.AppOpsManager.HistoricalOp getOpAt(@IntRange(from=0) int);
method @IntRange(from=0) public int getOpCount();
+ method @Nullable public String getTag();
method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalFeatureOps> CREATOR;
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.AttributedHistoricalOps> CREATOR;
+ }
+
+ public static final class AppOpsManager.AttributedOpEntry implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getLastAccessBackgroundTime(int);
+ method public long getLastAccessForegroundTime(int);
+ method public long getLastAccessTime(int);
+ method public long getLastAccessTime(int, int, int);
+ method public long getLastBackgroundDuration(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastBackgroundProxyInfo(int);
+ method public long getLastDuration(int);
+ method public long getLastDuration(int, int, int);
+ method public long getLastForegroundDuration(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastForegroundProxyInfo(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int);
+ method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int, int, int);
+ method public long getLastRejectBackgroundTime(int);
+ method public long getLastRejectForegroundTime(int);
+ method public long getLastRejectTime(int);
+ method public long getLastRejectTime(int, int, int);
+ method public boolean isRunning();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.AttributedOpEntry> CREATOR;
}
public static final class AppOpsManager.HistoricalOp implements android.os.Parcelable {
@@ -311,7 +334,7 @@
public static final class AppOpsManager.HistoricalOpsRequest.Builder {
ctor public AppOpsManager.HistoricalOpsRequest.Builder(long, long);
method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest build();
- method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setFeatureId(@Nullable String);
+ method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setAttributionTag(@Nullable String);
method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setFlags(int);
method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setOpNames(@Nullable java.util.List<java.lang.String>);
method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setPackageName(@Nullable String);
@@ -320,9 +343,9 @@
public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable {
method public int describeContents();
- method @IntRange(from=0) public int getFeatureCount();
- method @Nullable public android.app.AppOpsManager.HistoricalFeatureOps getFeatureOps(@NonNull String);
- method @NonNull public android.app.AppOpsManager.HistoricalFeatureOps getFeatureOpsAt(@IntRange(from=0) int);
+ method @Nullable public android.app.AppOpsManager.AttributedHistoricalOps getAttributedOps(@NonNull String);
+ method @NonNull public android.app.AppOpsManager.AttributedHistoricalOps getAttributedOpsAt(@IntRange(from=0) int);
+ method @IntRange(from=0) public int getAttributedOpsCount();
method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String);
method @NonNull public android.app.AppOpsManager.HistoricalOp getOpAt(@IntRange(from=0) int);
method @IntRange(from=0) public int getOpCount();
@@ -343,8 +366,8 @@
public static final class AppOpsManager.OpEntry implements android.os.Parcelable {
method public int describeContents();
+ method @NonNull public java.util.Map<java.lang.String,android.app.AppOpsManager.AttributedOpEntry> getAttributedOpEntries();
method @Deprecated public long getDuration();
- method @NonNull public java.util.Map<java.lang.String,android.app.AppOpsManager.OpFeatureEntry> getFeatures();
method public long getLastAccessBackgroundTime(int);
method public long getLastAccessForegroundTime(int);
method public long getLastAccessTime(int);
@@ -374,36 +397,13 @@
public static final class AppOpsManager.OpEventProxyInfo implements android.os.Parcelable {
method public int describeContents();
- method @Nullable public String getFeatureId();
+ method @Nullable public String getAttributionTag();
method @Nullable public String getPackageName();
method @IntRange(from=0) public int getUid();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpEventProxyInfo> CREATOR;
}
- public static final class AppOpsManager.OpFeatureEntry implements android.os.Parcelable {
- method public int describeContents();
- method public long getLastAccessBackgroundTime(int);
- method public long getLastAccessForegroundTime(int);
- method public long getLastAccessTime(int);
- method public long getLastAccessTime(int, int, int);
- method public long getLastBackgroundDuration(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastBackgroundProxyInfo(int);
- method public long getLastDuration(int);
- method public long getLastDuration(int, int, int);
- method public long getLastForegroundDuration(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastForegroundProxyInfo(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int);
- method @Nullable public android.app.AppOpsManager.OpEventProxyInfo getLastProxyInfo(int, int, int);
- method public long getLastRejectBackgroundTime(int);
- method public long getLastRejectForegroundTime(int);
- method public long getLastRejectTime(int);
- method public long getLastRejectTime(int, int, int);
- method public boolean isRunning();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.OpFeatureEntry> CREATOR;
- }
-
public static final class AppOpsManager.PackageOps implements android.os.Parcelable {
method public int describeContents();
method @NonNull public java.util.List<android.app.AppOpsManager.OpEntry> getOps();
@@ -428,6 +428,7 @@
method public boolean isBlockableSystem();
method public boolean isImportanceLockedByCriticalDeviceFunction();
method public boolean isImportanceLockedByOEM();
+ method public void lockFields(int);
method public void setBlockableSystem(boolean);
method public void setDeleted(boolean);
method public void setFgServiceShown(boolean);
@@ -435,6 +436,7 @@
method public void setImportanceLockedByOEM(boolean);
method public void setImportantConversation(boolean);
method public void setOriginalImportance(int);
+ field public static final int USER_LOCKED_SOUND = 32; // 0x20
}
public final class NotificationChannelGroup implements android.os.Parcelable {
@@ -463,7 +465,7 @@
public final class RuntimeAppOpAccessMessage implements android.os.Parcelable {
ctor public RuntimeAppOpAccessMessage(@IntRange(from=0L) int, @IntRange(from=0L) int, @NonNull String, @Nullable String, @NonNull String, int);
method public int describeContents();
- method @Nullable public String getFeatureId();
+ method @Nullable public String getAttributionTag();
method @NonNull public String getMessage();
method @NonNull public String getOp();
method @NonNull public String getPackageName();
@@ -3743,7 +3745,7 @@
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method @Nullable public static android.content.ComponentName getDefaultRespondViaMessageApplication(@NonNull android.content.Context, boolean);
method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
- method public int getEmergencyNumberDbVersion();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getEmergencyNumberDbVersion();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index f84e4b5..8f5e49d 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -113,7 +113,7 @@
Status Idmap2Service::createIdmap(const std::string& target_apk_path,
const std::string& overlay_apk_path, int32_t fulfilled_policies,
bool enforce_overlayable, int32_t user_id ATTRIBUTE_UNUSED,
- std::unique_ptr<std::string>* _aidl_return) {
+ aidl::nullable<std::string>* _aidl_return) {
assert(_aidl_return);
SYSTRACE << "Idmap2Service::createIdmap " << target_apk_path << " " << overlay_apk_path;
_aidl_return->reset(nullptr);
@@ -155,7 +155,7 @@
return error("failed to write to idmap path " + idmap_path);
}
- *_aidl_return = std::make_unique<std::string>(idmap_path);
+ *_aidl_return = aidl::make_nullable<std::string>(idmap_path);
return ok();
}
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
index 94d2af4..b6f5136 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.h
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -19,9 +19,7 @@
#include <android-base/unique_fd.h>
#include <binder/BinderService.h>
-
-#include <memory>
-#include <string>
+#include <binder/Nullable.h>
#include "android/os/BnIdmap2.h"
@@ -46,7 +44,7 @@
binder::Status createIdmap(const std::string& target_apk_path,
const std::string& overlay_apk_path, int32_t fulfilled_policies,
bool enforce_overlayable, int32_t user_id,
- std::unique_ptr<std::string>* _aidl_return) override;
+ aidl::nullable<std::string>* _aidl_return) override;
};
} // namespace android::os
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 32a5243..bd5bdc6 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -402,7 +402,7 @@
}
// Pulled events will start at field 10000.
- // Next: 10076
+ // Next: 10080
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000 [(module) = "framework"];
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001 [(module) = "framework"];
@@ -485,7 +485,11 @@
PackageNotificationChannelGroupPreferences package_notification_channel_group_preferences =
10073 [(module) = "framework"];
GnssStats gnss_stats = 10074 [(module) = "framework"];
- AppFeaturesOps app_features_ops = 10075 [(module) = "framework"];
+ AttributedAppOps attributed_app_ops = 10075 [(module) = "framework"];
+ VoiceCallSession voice_call_session = 10076 [(module) = "telephony"];
+ VoiceCallRatUsage voice_call_rat_usage = 10077 [(module) = "telephony"];
+ SimSlotState sim_slot_state = 10078 [(module) = "telephony"];
+ SupportedRadioAccessFamily supported_radio_access_family = 10079 [(module) = "telephony"];
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -4477,8 +4481,7 @@
* after an OTA.
*
* Logged from:
- * - system/core/fs_mgr/libsnapshot/snapshot.cpp
- * - system/core/fs_mgr/libsnapshot/snapshotctl.cpp
+ * - system/update_engine/cleanup_previous_update_action.cc
*/
message SnapshotMergeReported {
// Keep in sync with
@@ -7600,18 +7603,19 @@
}
/**
- * Historical app ops data per package and features.
+ * Historical app ops data per package and attribution tag.
*/
-message AppFeaturesOps {
+message AttributedAppOps {
// Uid of the package requesting the op
optional int32 uid = 1 [(is_uid) = true];
// Name of the package performing the op
optional string package_name = 2;
- // feature id; provided by developer when accessing related API, limited at 50 chars by API.
- // Features must be provided through manifest using <feature> tag available in R and above.
- optional string feature_id = 3;
+ // tag; provided by developer when accessing related API, limited at 50 chars by API.
+ // Attributions must be provided through manifest using <attribution> tag available in R and
+ // above.
+ optional string tag = 3;
// operation id; maps to the OPSTR_* constants in AppOpsManager.java
optional string op = 4;
@@ -8473,9 +8477,11 @@
// operation string id per OPSTR_ constants in AppOpsManager.java
optional string op = 3;
- // feature id; provided by developer when accessing related API, limited at 50 chars by API.
- // Features must be provided through manifest using <feature> tag available in R and above.
- optional string feature_id = 4;
+ // attribution_tag; provided by developer when accessing related API, limited at 50 chars by
+ // API.
+ // Attributions must be provided through manifest using <attribution> tag available in R and
+ // above.
+ optional string attribution_tag = 4;
// message related to app op access, limited to 600 chars by API
optional string message = 5;
@@ -8672,6 +8678,154 @@
}
/**
+ * Pulls information for a single voice call.
+ *
+ * Each pull creates multiple atoms, one for each call. The sequence is randomized when pulled.
+ *
+ * Pulled from:
+ * frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/PersistPullers.java
+ */
+message VoiceCallSession {
+ // Bearer (IMS or CS) when the call started.
+ optional android.telephony.CallBearerEnum bearer_at_start = 1;
+
+ // Bearer (IMS or CS) when the call ended.
+ // The bearer may change during the call, e.g. due to SRVCC.
+ optional android.telephony.CallBearerEnum bearer_at_end = 2;
+
+ // Direction of the call (incoming or outgoing).
+ optional android.telephony.CallDirectionEnum direction = 3;
+
+ // Time spent setting up the call.
+ optional android.telephony.CallSetupDurationEnum setup_duration = 4;
+
+ // Whether the call ended before the setup was completed.
+ optional bool setup_failed = 5;
+
+ // IMS reason code or CS disconnect cause.
+ // For IMS, see: frameworks/base/telephony/java/android/telephony/ims/ImsReasonInfo.java
+ // For CS, see: frameworks/base/telephony/java/android/telephony/DisconnectCause.java
+ optional int32 disconnect_reason_code = 6;
+
+ // IMS extra code or CS precise disconnect cause.
+ // For IMS, this code is vendor-specific
+ // For CS, see: frameworks/base/telephony/java/android/telephony/PreciseDisconnectCause.java
+ optional int32 disconnect_extra_code = 7;
+
+ // IMS extra message or CS vendor cause.
+ optional string disconnect_extra_message = 8;
+
+ // Radio access technology (RAT) used when call started.
+ optional android.telephony.NetworkTypeEnum rat_at_start = 9;
+
+ // Radio access technology (RAT) used when call terminated.
+ optional android.telephony.NetworkTypeEnum rat_at_end = 10;
+
+ // Number of times RAT changed during the call.
+ optional int64 rat_switch_count = 11;
+
+ // A bitmask of all codecs used during the call.
+ // See: frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
+ optional int64 codec_bitmask = 12;
+
+ // Number of other calls going on during call setup, for the same SIM slot.
+ optional int32 concurrent_call_count_at_start = 13;
+
+ // Number of other calls going on during call termination, for the same SIM slot.
+ optional int32 concurrent_call_count_at_end = 14;
+
+ // Index of the SIM is used, 0 for single-SIM devices.
+ optional int32 sim_slot_index = 15;
+
+ // Whether the device was in multi-SIM mode (with multiple active SIM profiles).
+ optional bool is_multi_sim = 16;
+
+ // Whether the call was made with an eSIM profile.
+ optional bool is_esim = 17;
+
+ // Carrier ID of the SIM card.
+ // See https://source.android.com/devices/tech/config/carrierid.
+ optional int32 carrier_id = 18;
+
+ // Whether an SRVCC has been completed successfully.
+ // SRVCC (CS fallback) should be recorded in the IMS call since there will be no more SRVCC
+ // events once the call is switched to CS.
+ optional bool srvcc_completed = 19;
+
+ // Number of SRVCC failures.
+ optional int64 srvcc_failure_count = 20;
+
+ // Number of SRVCC cancellations.
+ optional int64 srvcc_cancellation_count = 21;
+
+ // Whether the Real-Time Text (RTT) was ever used in the call.
+ optional bool rtt_enabled = 22;
+
+ // Whether this was an emergency call.
+ optional bool is_emergency = 23;
+
+ // Whether the call was performed while roaming.
+ optional bool is_roaming = 24;
+}
+
+/**
+ * Pulls voice call radio access technology (RAT) usage.
+ *
+ * Each pull creates multiple atoms, one for each carrier/RAT, the order of which is irrelevant to
+ * time. The atom will be skipped if not enough data is available.
+ *
+ * Pulled from:
+ * frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/PersistPullers.java
+ */
+message VoiceCallRatUsage {
+ // Carrier ID (https://source.android.com/devices/tech/config/carrierid).
+ optional int32 carrier_id = 1;
+
+ // Radio access technology.
+ optional android.telephony.NetworkTypeEnum rat = 2;
+
+ // Total duration that voice calls spent on this carrier and RAT.
+ optional int64 total_duration_seconds = 3;
+
+ // Total number of calls using this carrier and RAT.
+ // A call is counted once even if it used the RAT multiple times.
+ optional int64 call_count = 4;
+}
+
+/**
+ * Pulls the number of active SIM slots and SIMs/eSIM profiles.
+ *
+ * Pulled from:
+ * frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/NonPersistPullers.java
+ */
+message SimSlotState {
+ // Number of active SIM slots (both physical and eSIM profiles) in the device.
+ optional int32 active_slot_count = 1;
+
+ // Number of SIM cards (both physical and active eSIM profiles).
+ // This number is always equal to or less than the number of active SIM slots.
+ optional int32 sim_count = 2;
+
+ // Number of active eSIM profiles.
+ // This number is always equal to or less than the number of SIMs.
+ optional int32 esim_count = 3;
+}
+
+/**
+ * Pulls supported cellular radio access technologies.
+ *
+ * This atom reports the capabilities of the device, rather than the network it has access to.
+ *
+ * Pulled from:
+ * frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/NonPersistPullers.java
+ */
+message SupportedRadioAccessFamily {
+ // A bitmask of supported radio technologies.
+ // See android.telephony.TelephonyManager.NetworkTypeBitMask.
+ optional int64 network_type_bitmask = 1;
+}
+
+/**
* Logs gnss stats from location service provider
*
* Pulled from:
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 3a3eea9..e7036bb 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -48,6 +48,7 @@
import android.util.SparseArray;
import android.view.Display;
import android.view.KeyEvent;
+import android.view.SurfaceControl;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
@@ -1937,8 +1938,8 @@
* to declare the capability to take screenshot by setting the
* {@link android.R.styleable#AccessibilityService_canTakeScreenshot}
* property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
- * Besides, This API is only supported for default display now
- * {@link Display#DEFAULT_DISPLAY}.
+ * This API only will support {@link Display#DEFAULT_DISPLAY} until {@link SurfaceControl}
+ * supports non-default displays.
* </p>
*
* @param displayId The logic display id, must be {@link Display#DEFAULT_DISPLAY} for
@@ -1948,11 +1949,17 @@
*
* @return {@code true} if the taking screenshot accepted, {@code false} if too little time
* has elapsed since the last screenshot, invalid display or internal errors.
+ * @throws IllegalArgumentException if displayId is not {@link Display#DEFAULT_DISPLAY}.
*/
public boolean takeScreenshot(int displayId, @NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<ScreenshotResult> callback) {
Preconditions.checkNotNull(executor, "executor cannot be null");
Preconditions.checkNotNull(callback, "callback cannot be null");
+
+ if (displayId != Display.DEFAULT_DISPLAY) {
+ throw new IllegalArgumentException("DisplayId isn't the default display");
+ }
+
final IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance().getConnection(
mConnectionId);
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index ca37e9b..2c41e8d 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -18,6 +18,7 @@
import android.annotation.CallSuper;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
@@ -269,6 +270,11 @@
private float mDurationScale = -1f;
/**
+ * Animation handler used to schedule updates for this animation.
+ */
+ private AnimationHandler mAnimationHandler;
+
+ /**
* Public constants
*/
@@ -1684,6 +1690,15 @@
* @hide
*/
public AnimationHandler getAnimationHandler() {
- return AnimationHandler.getInstance();
+ return mAnimationHandler != null ? mAnimationHandler : AnimationHandler.getInstance();
+ }
+
+ /**
+ * Sets the animation handler used to schedule updates for this animator or {@code null} to use
+ * the default handler.
+ * @hide
+ */
+ public void setAnimationHandler(@Nullable AnimationHandler animationHandler) {
+ mAnimationHandler = animationHandler;
}
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8d6bc72..6480a6a 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5829,7 +5829,7 @@
intent.prepareToLeaveProcess(this);
result = ActivityTaskManager.getService()
.startActivity(mMainThread.getApplicationThread(), getBasePackageName(),
- getFeatureId(), intent,
+ getAttributionTag(), intent,
intent.resolveTypeIfNeeded(getContentResolver()), mToken, mEmbeddedID,
requestCode, ActivityManager.START_FLAG_ONLY_IF_NEEDED, null, options);
} catch (RemoteException e) {
@@ -6624,12 +6624,10 @@
String packageName = getPackageName();
try {
data.prepareToLeaveProcess(this);
- IIntentSender target =
- ActivityManager.getService().getIntentSenderWithFeature(
- ActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName, getFeatureId(),
- mParent == null ? mToken : mParent.mToken,
- mEmbeddedID, requestCode, new Intent[] { data }, null, flags, null,
- getUserId());
+ IIntentSender target = ActivityManager.getService().getIntentSenderWithFeature(
+ ActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName, getAttributionTag(),
+ mParent == null ? mToken : mParent.mToken, mEmbeddedID, requestCode,
+ new Intent[]{data}, null, flags, null, getUserId());
return target != null ? new PendingIntent(target) : null;
} catch (RemoteException e) {
// Empty
diff --git a/core/java/android/app/AppOps.md b/core/java/android/app/AppOps.md
new file mode 100644
index 0000000..bee701a
--- /dev/null
+++ b/core/java/android/app/AppOps.md
@@ -0,0 +1,212 @@
+<!--
+ 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
+ -->
+
+# App-ops
+
+App-ops are used for two purposes: Access control and tracking.
+
+App-ops cover a wide variety of functionality from helping with runtime permissions to battery
+consumption tracking.
+
+App-ops are defined in `AppOpsManager` as `OP_...` and need to be continuously numbered. The
+integer values of the app-ops are not exposed. For app-ops visible to 3rd party apps,
+the name of the app-op might be exposed as `OPSTR_`. As the integers are not part of the API, they
+might (and have) changed between platform versions and OEM implementations.
+`AppOpsManager.opToPublicName` and `AppOpsManager.strOpToOp` allow for conversion between integer
+and string identifier for the op.
+
+## App-ops as access restrictions
+
+App-ops can either be controlled for each [uid](../os/Users.md#int-uid) or for each package. Which
+one is used depends on the API provider maintaining this app-op.
+
+For any security or privacy related app-ops the provider needs to control the app-op per uid
+as all security and privacy is based on uid in Android.
+
+App-op used for non-security related tasks are usually controlled per package to provide finer
+granularity.
+
+### Setting the app-op mode
+
+To control access the app-op can be set to:
+
+`MODE_DEFAULT`
+: Default behavior, might differ from app-op to app-op
+
+`MODE_ALLOWED`
+: Allow the access
+
+`MODE_FOREGROUND`
+: Allow the access but only if the app is currently in the [foreground](#foreground)
+
+`MODE_IGNORED`
+: Don't allow the access, i.e. don't perform the requested action or return dummy data
+
+`MODE_ERRORED`
+: Throw a `SecurityException` on access. This can be suppressed by using a `...noThrow` method to
+check the mode
+
+The initial state of an app-op is defined in `AppOpsManager.sOpDefaultMode`. Confusingly the
+initial state is often not `MODE_DEFAULT`
+
+Per-package modes can be set using `AppOpsManager.setMode` and per-uid modes can be set using
+`AppOpsManager.setUidMode`.
+
+**Warning**: Do not use `setMode` and `setUidMode` for the same app-op. Due to the way the
+internal storage for the mode works this can lead to very confusing behavior. If this ever happened
+by accident this needs to be cleaned up for any affected user as the app-op mode is retained over
+reboot.
+
+App-ops can also be set via the shell using the `appops set` command. The target package/uid can be
+defined via parameters to this command.
+
+The current state of the app-op can be read via the `appops get` command or via `dumpsys appops`.
+If the app-op is not mentioned in the output the app-op is in it's initial state.
+
+For example `dumpsys appops`:
+```
+[...]
+ Uid 2000:
+ [...]
+ COARSE_LOCATION: mode=foreground
+ START_FOREGROUND: mode=foreground
+ LEGACY_STORAGE: mode=ignore
+ [...]
+```
+
+### Guarding access based on app-ops
+
+API providers need to check the mode returned by `AppOpsManager.noteOp` if they are are allowing
+access to operations gated by the app-op. `AppOpsManager.unsafeCheckOp` should be used to check the
+mode if no access is granted. E.g. this can be for displaying app-op state in the UI or when
+checking the state before later calling `noteOp` anyway.
+
+If an operation refers to a time span (e.g. a audio-recording session) the API provider should
+use `AppOpsManager.startOp` and `AppOpsManager.finishOp` instead of `noteOp`.
+
+`noteOp` and `startOp` take a `packageName` and `featureId` parameter. These need to be read from
+the calling apps context as `Context.getOpPackageName` and `Context.getFeatureId`, then send to
+the data provider and then passed on the `noteOp`/`startOp` method.
+
+#### App-ops and permissions
+
+Access guarding is often done in combination with permissions using [runtime permissions
+](../permission/Permissions.md#runtime-permissions-and-app-ops) or [app-op permissions
+](../permission/Permissions.md#app-op-permissions). This is preferred over just using an app-op
+ as permissions a concept more familiar to app developers.
+
+### Foreground
+
+The `AppOpsService` tracks the apps' proc state (== foreground-ness) by following the
+`ActivityManagerService`'s proc state. It reduces the possible proc states to only those needed
+for app-ops. It also delays the changes by a _settle time_. This delay is needed as the proc state
+can fluctuate when switching apps. By delaying the change the appops service is not affected by
+those.
+
+The proc state is used for two use cases: Firstly, Tracking remembers the proc state for each
+tracked event. Secondly, `noteOp`/`checkOp` calls for app-op that are set to `MODE_FOREGROUND` are
+translated using the `AppOpsService.UidState.evalMode` method into `MODE_ALLOWED` when the app is
+counted as foreground and `MODE_IGNORED` when the app is counted as background. `checkOpRaw`
+calls are not affected.
+
+The current proc state for an app can be read from `dumpsys appops`. The tracking information can
+be read from `dumpsys appops`
+
+```
+Uid u0a118:
+ state=fg
+ capability=6
+```
+
+## App-ops for tracking
+
+App-ops track many important events, including all accesses to runtime permission protected
+APIs. This is done by tracking when an app-op was noted or started. The tracked data can only be
+read by system components.
+
+**Note:** Only `noteOp`/`startOp` calls are tracked; `unsafeCheckOp` is not tracked. Hence it is
+important to eventually call `noteOp` or `startOp` when providing access to protected operations
+or data.
+
+Some apps are forwarding access to other apps. E.g. an app might get the location from the
+system's location provider and then send the location further to a 3rd app. In this case the
+app passing on the data needs to call `AppOpsManager.noteProxyOp` to signal the access proxying.
+This might also make sense inside of a single app if the access is forwarded between two features of
+the app. In this case an app-op is noted for the forwarding app (proxy) and the app that received
+the data (proxied). As any app can do it is important to track how much the system trusts this
+proxy-access-tracking. For more details see `AppOpService.noteProxyOperation`.
+
+The tracking information can be read from `dumpsys appops` split by feature, proc state and
+proxying information with the syntax
+
+```
+Package THE_PACKAGE_NAME:
+ AN_APP_OP (CURRENT_MODE):
+ FEATURE_ID (or null for default feature)=[
+ ACCESS_OR_REJECT: [PROC_STATE-PROXYING_TAG] TIME proxy[INFO_ABOUT_PROXY IF_PROXY_ACCESS]
+```
+
+Example:
+
+```
+Package com.google.android.gms:
+ READ_CONTACTS (allow):
+ null=[
+ Access: [fgsvc-s] 2020-02-14 14:24:10.559 (-3d23h15m43s642ms)
+ Access: [fgsvc-tp] 2020-02-14 14:23:58.189 (-3d23h15m56s12ms)
+ ]
+ apkappcontext=[
+ Access: [fg-tp] 2020-02-17 14:24:54.721 (-23h14m59s480ms)
+ ]
+ com.google.android.gms.icing=[
+ Access: [fgsvc-tpd] 2020-02-14 14:26:27.018 (-3d23h13m27s183ms) proxy[uid=10070, pkg=com.android.providers.contacts, feature=null]
+ Access: [fg-tpd] 2020-02-18 02:26:08.711 (-11h13m45s490ms) proxy[uid=10070, pkg=com.android.providers.contacts, feature=null]
+ Access: [bg-tpd] 2020-02-14 14:34:55.310 (-3d23h4m58s891ms) proxy[uid=10070, pkg=com.android.providers.contacts, feature=null]
+ ]
+ MANAGE_EXTERNAL_STORAGE (default):
+ null=[
+ Reject: [fg-s]2020-02-18 08:00:04.444 (-5h39m49s757ms)
+ Reject: [bg-s]2020-02-18 08:00:04.427 (-5h39m49s774ms)
+ ]
+```
+
+### Tracking an app's own private data accesses
+
+An app can register an `AppOpsManager.OnOpNotedCallback` to get informed about what accesses the
+system is tracking for it. As each runtime permission has an associated app-op this API is
+particularly useful for an app that want to find unexpected private data accesses.
+
+## Listening to app-op events
+
+System apps (with the appropriate permissions) can listen to most app-op events, such as
+
+`noteOp`
+: `startWatchingNoted`
+
+`startOp`/`finishOp`
+: `startWatchingActive`
+
+mode changes
+: `startWatchingMode`
+
+[foreground](#foreground)-ness changes
+: `startWatchingMode` using the `WATCH_FOREGROUND_CHANGES` flag
+
+Watching such events is only ever as good as the tracked events. E.g. if the audio provider does
+not call `startOp` for a audio-session, the app's activeness for the record-audio app-op is not
+changed. Further there were cases where app-ops were noted even though no data was accessed or
+operation was performed. Hence before relying on the data from app-ops, double check if the data
+is actually reliable.
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 6564dc9..f6a79cd 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -27,6 +27,7 @@
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.app.usage.UsageStatsManager;
+import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.compat.annotation.UnsupportedAppUsage;
@@ -159,8 +160,8 @@
* <p>Some apps are forwarding access to other apps. E.g. an app might get the location from the
* system's location provider and then send the location further to a 3rd app. In this case the
* app passing on the data needs to call {@link #noteProxyOp} to signal the access proxying. This
- * might also make sense inside of a single app if the access is forwarded between two features of
- * the app.
+ * might also make sense inside of a single app if the access is forwarded between two parts of
+ * the tagged with different attribution tags.
*
* <p>An app can register an {@link OnOpNotedCallback} to get informed about what accesses the
* system is tracking for it. As each runtime permission has an associated app-op this API is
@@ -385,6 +386,13 @@
*/
public static final int WATCH_FOREGROUND_CHANGES = 1 << 0;
+ /**
+ * Flag for {@link #startWatchingMode} that causes the callback to happen on the switch-op
+ * instead the op the callback was registered. (This simulates pre-R behavior).
+ *
+ * @hide
+ */
+ public static final int CALL_BACK_ON_SWITCHED_OP = 1 << 1;
/**
* Flag to determine whether we should log noteOp/startOp calls to make sure they
@@ -2650,23 +2658,23 @@
private @IntRange(from = 0) int mUid;
/** Package of the proxy that noted the op */
private @Nullable String mPackageName;
- /** ID of the feature of the proxy that noted the op */
- private @Nullable String mFeatureId;
+ /** Attribution tag of the proxy that noted the op */
+ private @Nullable String mAttributionTag;
/**
* Reinit existing object with new state.
*
* @param uid UID of the proxy app that noted the op
* @param packageName Package of the proxy that noted the op
- * @param featureId ID of the feature of the proxy that noted the op
+ * @param attributionTag attribution tag of the proxy that noted the op
*
* @hide
*/
public void reinit(@IntRange(from = 0) int uid, @Nullable String packageName,
- @Nullable String featureId) {
+ @Nullable String attributionTag) {
mUid = Preconditions.checkArgumentNonnegative(uid);
mPackageName = packageName;
- mFeatureId = featureId;
+ mAttributionTag = attributionTag;
}
@@ -2691,21 +2699,21 @@
* UID of the proxy app that noted the op
* @param packageName
* Package of the proxy that noted the op
- * @param featureId
- * ID of the feature of the proxy that noted the op
+ * @param attributionTag
+ * Attribution tag of the proxy that noted the op
* @hide
*/
@DataClass.Generated.Member
public OpEventProxyInfo(
@IntRange(from = 0) int uid,
@Nullable String packageName,
- @Nullable String featureId) {
+ @Nullable String attributionTag) {
this.mUid = uid;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mUid,
"from", 0);
this.mPackageName = packageName;
- this.mFeatureId = featureId;
+ this.mAttributionTag = attributionTag;
// onConstructed(); // You can define this method to get a callback
}
@@ -2719,7 +2727,7 @@
public OpEventProxyInfo(@NonNull OpEventProxyInfo orig) {
mUid = orig.mUid;
mPackageName = orig.mPackageName;
- mFeatureId = orig.mFeatureId;
+ mAttributionTag = orig.mAttributionTag;
}
/**
@@ -2739,11 +2747,11 @@
}
/**
- * ID of the feature of the proxy that noted the op
+ * Attribution tag of the proxy that noted the op
*/
@DataClass.Generated.Member
- public @Nullable String getFeatureId() {
- return mFeatureId;
+ public @Nullable String getAttributionTag() {
+ return mAttributionTag;
}
@Override
@@ -2754,11 +2762,11 @@
byte flg = 0;
if (mPackageName != null) flg |= 0x2;
- if (mFeatureId != null) flg |= 0x4;
+ if (mAttributionTag != null) flg |= 0x4;
dest.writeByte(flg);
dest.writeInt(mUid);
if (mPackageName != null) dest.writeString(mPackageName);
- if (mFeatureId != null) dest.writeString(mFeatureId);
+ if (mAttributionTag != null) dest.writeString(mAttributionTag);
}
@Override
@@ -2775,14 +2783,14 @@
byte flg = in.readByte();
int uid = in.readInt();
String packageName = (flg & 0x2) == 0 ? null : in.readString();
- String featureId = (flg & 0x4) == 0 ? null : in.readString();
+ String attributionTag = (flg & 0x4) == 0 ? null : in.readString();
this.mUid = uid;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mUid,
"from", 0);
this.mPackageName = packageName;
- this.mFeatureId = featureId;
+ this.mAttributionTag = attributionTag;
// onConstructed(); // You can define this method to get a callback
}
@@ -2806,7 +2814,7 @@
time = 1576814974615L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/app/AppOpsManager.java",
- inputSignatures = "private @android.annotation.IntRange(from=0L) int mUid\nprivate @android.annotation.Nullable java.lang.String mPackageName\nprivate @android.annotation.Nullable java.lang.String mFeatureId\npublic void reinit(int,java.lang.String,java.lang.String)\nclass OpEventProxyInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genHiddenCopyConstructor=true)")
+ inputSignatures = "private @android.annotation.IntRange(from=0L) int mUid\nprivate @android.annotation.Nullable java.lang.String mPackageName\nprivate @android.annotation.Nullable java.lang.String mAttributionTag\npublic void reinit(int,java.lang.String,java.lang.String)\nclass OpEventProxyInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genHiddenCopyConstructor=true)")
@Deprecated
private void __metadata() {}
*/
@@ -3005,7 +3013,7 @@
/**
* Last {@link #noteOp} and {@link #startOp} events performed for a single op and a specific
- * {@link Context#createFeatureContext(String) feature} for all uidModes and opFlags.
+ * {@link Context#createAttributionContext(String) attribution} for all uidModes and opFlags.
*
* @hide
*/
@@ -3014,7 +3022,7 @@
@Immutable
// @DataClass(genHiddenConstructor = true) codegen verifier is broken
@DataClass.Suppress({"getAccessEvents", "getRejectEvents", "getOp"})
- public static final class OpFeatureEntry implements Parcelable {
+ public static final class AttributedOpEntry implements Parcelable {
/** The code of the op */
private final @IntRange(from = 0, to = _NUM_OP - 1) int mOp;
/** Whether the op is running */
@@ -3313,8 +3321,8 @@
}
/**
- * Gets the proxy info of the app that performed the last access on behalf of this feature
- * and as a result blamed the op on this app.
+ * Gets the proxy info of the app that performed the last access on behalf of this
+ * attribution and as a result blamed the op on this attribution.
*
* @param flags The op flags
*
@@ -3331,7 +3339,7 @@
/**
* Gets the proxy info of the app that performed the last foreground access on behalf of
- * this feature and as a result blamed the op on this app.
+ * this attribution and as a result blamed the op on this attribution.
*
* @param flags The op flags
*
@@ -3349,7 +3357,7 @@
/**
* Gets the proxy info of the app that performed the last background access on behalf of
- * this feature and as a result blamed the op on this app.
+ * this attribution and as a result blamed the op on this attribution.
*
* @param flags The op flags
*
@@ -3366,8 +3374,8 @@
}
/**
- * Gets the proxy info of the app that performed the last access on behalf of this feature
- * and as a result blamed the op on this app.
+ * Gets the proxy info of the app that performed the last access on behalf of this
+ * attribution and as a result blamed the op on this attribution.
*
* @param fromUidState The lowest UID state for which to query
* @param toUidState The highest UID state for which to query (inclusive)
@@ -3442,7 +3450,7 @@
/**
- * Creates a new OpFeatureEntry.
+ * Creates a new OpAttributionEntry.
*
* @param op
* The code of the op
@@ -3455,7 +3463,7 @@
* @hide
*/
@DataClass.Generated.Member
- public OpFeatureEntry(
+ public AttributedOpEntry(
@IntRange(from = 0, to = _NUM_OP - 1) int op,
boolean running,
@Nullable LongSparseArray<NoteOpEvent> accessEvents,
@@ -3525,7 +3533,7 @@
/** @hide */
@SuppressWarnings({"unchecked", "RedundantCast"})
@DataClass.Generated.Member
- /* package-private */ OpFeatureEntry(@NonNull Parcel in) {
+ /* package-private */ AttributedOpEntry(@NonNull Parcel in) {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
@@ -3548,16 +3556,16 @@
}
@DataClass.Generated.Member
- public static final @NonNull Parcelable.Creator<OpFeatureEntry> CREATOR
- = new Parcelable.Creator<OpFeatureEntry>() {
+ public static final @NonNull Parcelable.Creator<AttributedOpEntry> CREATOR
+ = new Parcelable.Creator<AttributedOpEntry>() {
@Override
- public OpFeatureEntry[] newArray(int size) {
- return new OpFeatureEntry[size];
+ public AttributedOpEntry[] newArray(int size) {
+ return new AttributedOpEntry[size];
}
@Override
- public OpFeatureEntry createFromParcel(@NonNull Parcel in) {
- return new OpFeatureEntry(in);
+ public AttributedOpEntry createFromParcel(@NonNull Parcel in) {
+ return new AttributedOpEntry(in);
}
};
@@ -3566,7 +3574,7 @@
time = 1574809856239L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/app/AppOpsManager.java",
- inputSignatures = "private final @android.annotation.IntRange(from=0L, to=_NUM_OP - 1) int mOp\nprivate final boolean mRunning\nprivate final @com.android.internal.util.DataClass.ParcelWith(android.app.OpFeatureEntry.LongSparseArrayParceling.class) @android.annotation.Nullable android.util.LongSparseArray<android.app.NoteOpEvent> mAccessEvents\nprivate final @com.android.internal.util.DataClass.ParcelWith(android.app.OpFeatureEntry.LongSparseArrayParceling.class) @android.annotation.Nullable android.util.LongSparseArray<android.app.NoteOpEvent> mRejectEvents\npublic @android.annotation.NonNull android.util.ArraySet<java.lang.Long> collectKeys()\npublic @android.app.UidState int getLastAccessUidState(int)\npublic @android.app.UidState int getLastForegroundAccessUidState(int)\npublic @android.app.UidState int getLastBackgroundAccessUidState(int)\npublic @android.app.UidState int getLastRejectUidState(int)\npublic @android.app.UidState int getLastForegroundRejectUidState(int)\npublic @android.app.UidState int getLastBackgroundRejectUidState(int)\npublic long getAccessTime(int,int)\npublic long getRejectTime(int,int)\npublic long getDuration(int,int)\npublic int getProxyUid(int,int)\npublic @android.annotation.Nullable java.lang.String getProxyPackageName(int,int)\npublic @android.annotation.Nullable java.lang.String getProxyFeatureId(int,int)\nclass OpFeatureEntry extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
+ inputSignatures = "private final @android.annotation.IntRange(from=0L, to=_NUM_OP - 1) int mOp\nprivate final boolean mRunning\nprivate final @com.android.internal.util.DataClass.ParcelWith(android.app.OpAttributionEntry.LongSparseArrayParceling.class) @android.annotation.Nullable android.util.LongSparseArray<android.app.NoteOpEvent> mAccessEvents\nprivate final @com.android.internal.util.DataClass.ParcelWith(android.app.OpAttributionEntry.LongSparseArrayParceling.class) @android.annotation.Nullable android.util.LongSparseArray<android.app.NoteOpEvent> mRejectEvents\npublic @android.annotation.NonNull android.util.ArraySet<java.lang.Long> collectKeys()\npublic @android.app.UidState int getLastAccessUidState(int)\npublic @android.app.UidState int getLastForegroundAccessUidState(int)\npublic @android.app.UidState int getLastBackgroundAccessUidState(int)\npublic @android.app.UidState int getLastRejectUidState(int)\npublic @android.app.UidState int getLastForegroundRejectUidState(int)\npublic @android.app.UidState int getLastBackgroundRejectUidState(int)\npublic long getAccessTime(int,int)\npublic long getRejectTime(int,int)\npublic long getDuration(int,int)\npublic int getProxyUid(int,int)\npublic @android.annotation.Nullable java.lang.String getProxyPackageName(int,int)\npublic @android.annotation.Nullable java.lang.String getProxyAttributionTag(int,int)\nclass OpAttributionEntry extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}
*/
@@ -3592,8 +3600,8 @@
private final @IntRange(from = 0, to = _NUM_OP - 1) int mOp;
/** The mode of the op */
private final @Mode int mMode;
- /** The features that have been used when checking the op */
- private final @NonNull Map<String, OpFeatureEntry> mFeatures;
+ /** The attributed entries by attribution tag */
+ private final @NonNull Map<String, AttributedOpEntry> mAttributedOpEntries;
/**
* @hide
@@ -3634,7 +3642,7 @@
* @see #getLastAccessForegroundTime(int)
* @see #getLastAccessBackgroundTime(int)
* @see #getLastAccessTime(int, int, int)
- * @see OpFeatureEntry#getLastAccessTime(int)
+ * @see AttributedOpEntry#getLastAccessTime(int)
*/
public long getLastAccessTime(@OpFlags int flags) {
return getLastAccessTime(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, flags);
@@ -3651,7 +3659,7 @@
* @see #getLastAccessTime(int)
* @see #getLastAccessBackgroundTime(int)
* @see #getLastAccessTime(int, int, int)
- * @see OpFeatureEntry#getLastAccessForegroundTime(int)
+ * @see AttributedOpEntry#getLastAccessForegroundTime(int)
*/
public long getLastAccessForegroundTime(@OpFlags int flags) {
return getLastAccessTime(MAX_PRIORITY_UID_STATE, resolveFirstUnrestrictedUidState(mOp),
@@ -3669,7 +3677,7 @@
* @see #getLastAccessTime(int)
* @see #getLastAccessForegroundTime(int)
* @see #getLastAccessTime(int, int, int)
- * @see OpFeatureEntry#getLastAccessBackgroundTime(int)
+ * @see AttributedOpEntry#getLastAccessBackgroundTime(int)
*/
public long getLastAccessBackgroundTime(@OpFlags int flags) {
return getLastAccessTime(resolveLastRestrictedUidState(mOp), MIN_PRIORITY_UID_STATE,
@@ -3686,13 +3694,14 @@
private @Nullable NoteOpEvent getLastAccessEvent(@UidState int fromUidState,
@UidState int toUidState, @OpFlags int flags) {
NoteOpEvent lastAccessEvent = null;
- for (OpFeatureEntry featureEntry : mFeatures.values()) {
- NoteOpEvent lastFeatureAccessEvent = featureEntry.getLastAccessEvent(fromUidState,
- toUidState, flags);
+ for (AttributedOpEntry attributionEntry : mAttributedOpEntries.values()) {
+ NoteOpEvent lastAttributionAccessEvent = attributionEntry.getLastAccessEvent(
+ fromUidState, toUidState, flags);
- if (lastAccessEvent == null || (lastFeatureAccessEvent != null
- && lastFeatureAccessEvent.getNoteTime() > lastAccessEvent.getNoteTime())) {
- lastAccessEvent = lastFeatureAccessEvent;
+ if (lastAccessEvent == null || (lastAttributionAccessEvent != null
+ && lastAttributionAccessEvent.getNoteTime()
+ > lastAccessEvent.getNoteTime())) {
+ lastAccessEvent = lastAttributionAccessEvent;
}
}
@@ -3712,7 +3721,7 @@
* @see #getLastAccessTime(int)
* @see #getLastAccessForegroundTime(int)
* @see #getLastAccessBackgroundTime(int)
- * @see OpFeatureEntry#getLastAccessTime(int, int, int)
+ * @see AttributedOpEntry#getLastAccessTime(int, int, int)
*/
public long getLastAccessTime(@UidState int fromUidState, @UidState int toUidState,
@OpFlags int flags) {
@@ -3748,7 +3757,7 @@
* @see #getLastRejectForegroundTime(int)
* @see #getLastRejectBackgroundTime(int)
* @see #getLastRejectTime(int, int, int)
- * @see OpFeatureEntry#getLastRejectTime(int)
+ * @see AttributedOpEntry#getLastRejectTime(int)
*/
public long getLastRejectTime(@OpFlags int flags) {
return getLastRejectTime(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, flags);
@@ -3765,7 +3774,7 @@
* @see #getLastRejectTime(int)
* @see #getLastRejectBackgroundTime(int)
* @see #getLastRejectTime(int, int, int)
- * @see OpFeatureEntry#getLastRejectForegroundTime(int)
+ * @see AttributedOpEntry#getLastRejectForegroundTime(int)
*/
public long getLastRejectForegroundTime(@OpFlags int flags) {
return getLastRejectTime(MAX_PRIORITY_UID_STATE, resolveFirstUnrestrictedUidState(mOp),
@@ -3783,7 +3792,7 @@
* @see #getLastRejectTime(int)
* @see #getLastRejectForegroundTime(int)
* @see #getLastRejectTime(int, int, int)
- * @see OpFeatureEntry#getLastRejectBackgroundTime(int)
+ * @see AttributedOpEntry#getLastRejectBackgroundTime(int)
*/
public long getLastRejectBackgroundTime(@OpFlags int flags) {
return getLastRejectTime(resolveLastRestrictedUidState(mOp), MIN_PRIORITY_UID_STATE,
@@ -3800,13 +3809,14 @@
private @Nullable NoteOpEvent getLastRejectEvent(@UidState int fromUidState,
@UidState int toUidState, @OpFlags int flags) {
NoteOpEvent lastAccessEvent = null;
- for (OpFeatureEntry featureEntry : mFeatures.values()) {
- NoteOpEvent lastFeatureAccessEvent = featureEntry.getLastRejectEvent(fromUidState,
- toUidState, flags);
+ for (AttributedOpEntry attributionEntry : mAttributedOpEntries.values()) {
+ NoteOpEvent lastAttributionAccessEvent = attributionEntry.getLastRejectEvent(
+ fromUidState, toUidState, flags);
- if (lastAccessEvent == null || (lastFeatureAccessEvent != null
- && lastFeatureAccessEvent.getNoteTime() > lastAccessEvent.getNoteTime())) {
- lastAccessEvent = lastFeatureAccessEvent;
+ if (lastAccessEvent == null || (lastAttributionAccessEvent != null
+ && lastAttributionAccessEvent.getNoteTime()
+ > lastAccessEvent.getNoteTime())) {
+ lastAccessEvent = lastAttributionAccessEvent;
}
}
@@ -3827,7 +3837,7 @@
* @see #getLastRejectForegroundTime(int)
* @see #getLastRejectBackgroundTime(int)
* @see #getLastRejectTime(int, int, int)
- * @see OpFeatureEntry#getLastRejectTime(int, int, int)
+ * @see AttributedOpEntry#getLastRejectTime(int, int, int)
*/
public long getLastRejectTime(@UidState int fromUidState, @UidState int toUidState,
@OpFlags int flags) {
@@ -3843,8 +3853,8 @@
* @return Whether the operation is running.
*/
public boolean isRunning() {
- for (OpFeatureEntry opFeatureEntry : mFeatures.values()) {
- if (opFeatureEntry.isRunning()) {
+ for (AttributedOpEntry opAttributionEntry : mAttributedOpEntries.values()) {
+ if (opAttributionEntry.isRunning()) {
return true;
}
}
@@ -3870,7 +3880,7 @@
* @see #getLastForegroundDuration(int)
* @see #getLastBackgroundDuration(int)
* @see #getLastDuration(int, int, int)
- * @see OpFeatureEntry#getLastDuration(int)
+ * @see AttributedOpEntry#getLastDuration(int)
*/
public long getLastDuration(@OpFlags int flags) {
return getLastDuration(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, flags);
@@ -3886,7 +3896,7 @@
* @see #getLastDuration(int)
* @see #getLastBackgroundDuration(int)
* @see #getLastDuration(int, int, int)
- * @see OpFeatureEntry#getLastForegroundDuration(int)
+ * @see AttributedOpEntry#getLastForegroundDuration(int)
*/
public long getLastForegroundDuration(@OpFlags int flags) {
return getLastDuration(MAX_PRIORITY_UID_STATE, resolveFirstUnrestrictedUidState(mOp),
@@ -3903,7 +3913,7 @@
* @see #getLastDuration(int)
* @see #getLastForegroundDuration(int)
* @see #getLastDuration(int, int, int)
- * @see OpFeatureEntry#getLastBackgroundDuration(int)
+ * @see AttributedOpEntry#getLastBackgroundDuration(int)
*/
public long getLastBackgroundDuration(@OpFlags int flags) {
return getLastDuration(resolveLastRestrictedUidState(mOp), MIN_PRIORITY_UID_STATE,
@@ -3922,7 +3932,7 @@
* @see #getLastDuration(int)
* @see #getLastForegroundDuration(int)
* @see #getLastBackgroundDuration(int)
- * @see OpFeatureEntry#getLastDuration(int, int, int)
+ * @see AttributedOpEntry#getLastDuration(int, int, int)
*/
public long getLastDuration(@UidState int fromUidState, @UidState int toUidState,
@OpFlags int flags) {
@@ -3997,7 +4007,7 @@
* @see #getLastForegroundProxyInfo(int)
* @see #getLastBackgroundProxyInfo(int)
* @see #getLastProxyInfo(int, int, int)
- * @see OpFeatureEntry#getLastProxyInfo(int)
+ * @see AttributedOpEntry#getLastProxyInfo(int)
*/
public @Nullable OpEventProxyInfo getLastProxyInfo(@OpFlags int flags) {
return getLastProxyInfo(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, flags);
@@ -4014,7 +4024,7 @@
* @see #getLastProxyInfo(int)
* @see #getLastBackgroundProxyInfo(int)
* @see #getLastProxyInfo(int, int, int)
- * @see OpFeatureEntry#getLastForegroundProxyInfo(int)
+ * @see AttributedOpEntry#getLastForegroundProxyInfo(int)
*/
public @Nullable OpEventProxyInfo getLastForegroundProxyInfo(@OpFlags int flags) {
return getLastProxyInfo(MAX_PRIORITY_UID_STATE, resolveFirstUnrestrictedUidState(mOp),
@@ -4032,7 +4042,7 @@
* @see #getLastProxyInfo(int)
* @see #getLastForegroundProxyInfo(int)
* @see #getLastProxyInfo(int, int, int)
- * @see OpFeatureEntry#getLastBackgroundProxyInfo(int)
+ * @see AttributedOpEntry#getLastBackgroundProxyInfo(int)
*/
public @Nullable OpEventProxyInfo getLastBackgroundProxyInfo(@OpFlags int flags) {
return getLastProxyInfo(resolveLastRestrictedUidState(mOp), MIN_PRIORITY_UID_STATE,
@@ -4052,7 +4062,7 @@
* @see #getLastProxyInfo(int)
* @see #getLastForegroundProxyInfo(int)
* @see #getLastBackgroundProxyInfo(int)
- * @see OpFeatureEntry#getLastProxyInfo(int, int, int)
+ * @see AttributedOpEntry#getLastProxyInfo(int, int, int)
*/
public @Nullable OpEventProxyInfo getLastProxyInfo(@UidState int fromUidState,
@UidState int toUidState, @OpFlags int flags) {
@@ -4086,15 +4096,15 @@
* The code of the op
* @param mode
* The mode of the op
- * @param features
- * The features that have been used when checking the op
+ * @param attributedOpEntries
+ * The attributions that have been used when noting the op
* @hide
*/
@DataClass.Generated.Member
public OpEntry(
@IntRange(from = 0, to = _NUM_OP - 1) int op,
@Mode int mode,
- @NonNull Map<String,OpFeatureEntry> features) {
+ @NonNull Map<String, AttributedOpEntry> attributedOpEntries) {
this.mOp = op;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mOp,
@@ -4103,9 +4113,9 @@
this.mMode = mode;
com.android.internal.util.AnnotationValidations.validate(
Mode.class, null, mMode);
- this.mFeatures = features;
+ this.mAttributedOpEntries = attributedOpEntries;
com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mFeatures);
+ NonNull.class, null, mAttributedOpEntries);
// onConstructed(); // You can define this method to get a callback
}
@@ -4119,14 +4129,14 @@
}
/**
- * The features that have been used when checking the op keyed by id of the feature.
+ * The attributed entries keyed by attribution tag.
*
- * @see Context#createFeatureContext(String)
+ * @see Context#createAttributionContext(String)
* @see #noteOp(String, int, String, String, String)
*/
@DataClass.Generated.Member
- public @NonNull Map<String,OpFeatureEntry> getFeatures() {
- return mFeatures;
+ public @NonNull Map<String, AttributedOpEntry> getAttributedOpEntries() {
+ return mAttributedOpEntries;
}
@Override
@@ -4137,7 +4147,7 @@
dest.writeInt(mOp);
dest.writeInt(mMode);
- dest.writeMap(mFeatures);
+ dest.writeMap(mAttributedOpEntries);
}
@Override
@@ -4153,8 +4163,8 @@
int op = in.readInt();
int mode = in.readInt();
- Map<String,OpFeatureEntry> features = new java.util.LinkedHashMap<>();
- in.readMap(features, OpFeatureEntry.class.getClassLoader());
+ Map<String, AttributedOpEntry> attributions = new java.util.LinkedHashMap<>();
+ in.readMap(attributions, AttributedOpEntry.class.getClassLoader());
this.mOp = op;
com.android.internal.util.AnnotationValidations.validate(
@@ -4164,9 +4174,9 @@
this.mMode = mode;
com.android.internal.util.AnnotationValidations.validate(
Mode.class, null, mMode);
- this.mFeatures = features;
+ this.mAttributedOpEntries = attributions;
com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mFeatures);
+ NonNull.class, null, mAttributedOpEntries);
// onConstructed(); // You can define this method to get a callback
}
@@ -4190,7 +4200,7 @@
time = 1574809856259L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/app/AppOpsManager.java",
- inputSignatures = "private final @android.annotation.IntRange(from=0L, to=_NUM_OP - 1) int mOp\nprivate final @android.app.Mode int mMode\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,android.app.OpFeatureEntry> mFeatures\npublic @android.annotation.UnsupportedAppUsage(maxTargetSdk=Build.VERSION_CODES.Q, publicAlternatives=\"{@code \" + \"#getOpStr()}\") int getOp()\npublic @android.annotation.NonNull java.lang.String getOpStr()\npublic @java.lang.Deprecated @android.annotation.UnsupportedAppUsage(maxTargetSdk=Build.VERSION_CODES.Q, publicAlternatives=\"{@code \" + \"#getAccessTime(int, int)}\") long getTime()\npublic @java.lang.Deprecated long getLastAccessTime(int)\npublic @java.lang.Deprecated long getLastAccessForegroundTime(int)\npublic @java.lang.Deprecated long getLastAccessBackgroundTime(int)\npublic @java.lang.Deprecated long getLastAccessTime(int,int,int)\npublic @java.lang.Deprecated @android.annotation.UnsupportedAppUsage(maxTargetSdk=Build.VERSION_CODES.Q, publicAlternatives=\"{@code \" + \"#getLastRejectTime(int, int, int)}\") long getRejectTime()\npublic @java.lang.Deprecated long getLastRejectTime(int)\npublic @java.lang.Deprecated long getLastRejectForegroundTime(int)\npublic @java.lang.Deprecated long getLastRejectBackgroundTime(int)\npublic @java.lang.Deprecated long getLastRejectTime(int,int,int)\npublic long getAccessTime(int,int)\npublic long getRejectTime(int,int)\npublic boolean isRunning()\nprivate android.app.NoteOpEvent getLastAccessEvent(int,int,int)\npublic @java.lang.Deprecated long getDuration()\npublic @java.lang.Deprecated long getLastForegroundDuration(int)\npublic @java.lang.Deprecated long getLastBackgroundDuration(int)\npublic @java.lang.Deprecated long getLastDuration(int,int,int)\npublic @java.lang.Deprecated int getProxyUid()\npublic @java.lang.Deprecated @android.annotation.Nullable java.lang.String getProxyPackageName()\nprivate @android.app.UidState int getLastAccessUidStateForFlagsInStatesOfAllFeatures(int,int,int)\npublic @android.app.UidState int getLastAccessUidState(int)\npublic @android.app.UidState int getLastForegroundAccessUidState(int)\npublic @android.app.UidState int getLastBackgroundAccessUidState(int)\nprivate @android.app.UidState int getLastRejectUidStateForFlagsInStatesOfAllFeatures(int,int,int)\npublic @android.app.UidState int getLastRejectUidState(int)\npublic @android.app.UidState int getLastForegroundRejectUidState(int)\npublic @android.app.UidState int getLastBackgroundRejectUidState(int)\npublic long getDuration(int,int)\npublic int getProxyUid(int,int)\nprivate int getProxyUid(int,int,int)\npublic @android.annotation.Nullable java.lang.String getProxyPackageName(int,int)\nprivate @android.annotation.Nullable java.lang.String getProxyPackageName(int,int,int)\nclass OpEntry extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
+ inputSignatures = "private final @android.annotation.IntRange(from=0L, to=_NUM_OP - 1) int mOp\nprivate final @android.app.Mode int mMode\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,android.app.OpAttributionEntry> mAttributions\npublic @android.annotation.UnsupportedAppUsage(maxTargetSdk=Build.VERSION_CODES.Q, publicAlternatives=\"{@code \" + \"#getOpStr()}\") int getOp()\npublic @android.annotation.NonNull java.lang.String getOpStr()\npublic @java.lang.Deprecated @android.annotation.UnsupportedAppUsage(maxTargetSdk=Build.VERSION_CODES.Q, publicAlternatives=\"{@code \" + \"#getAccessTime(int, int)}\") long getTime()\npublic @java.lang.Deprecated long getLastAccessTime(int)\npublic @java.lang.Deprecated long getLastAccessForegroundTime(int)\npublic @java.lang.Deprecated long getLastAccessBackgroundTime(int)\npublic @java.lang.Deprecated long getLastAccessTime(int,int,int)\npublic @java.lang.Deprecated @android.annotation.UnsupportedAppUsage(maxTargetSdk=Build.VERSION_CODES.Q, publicAlternatives=\"{@code \" + \"#getLastRejectTime(int, int, int)}\") long getRejectTime()\npublic @java.lang.Deprecated long getLastRejectTime(int)\npublic @java.lang.Deprecated long getLastRejectForegroundTime(int)\npublic @java.lang.Deprecated long getLastRejectBackgroundTime(int)\npublic @java.lang.Deprecated long getLastRejectTime(int,int,int)\npublic long getAccessTime(int,int)\npublic long getRejectTime(int,int)\npublic boolean isRunning()\nprivate android.app.NoteOpEvent getLastAccessEvent(int,int,int)\npublic @java.lang.Deprecated long getDuration()\npublic @java.lang.Deprecated long getLastForegroundDuration(int)\npublic @java.lang.Deprecated long getLastBackgroundDuration(int)\npublic @java.lang.Deprecated long getLastDuration(int,int,int)\npublic @java.lang.Deprecated int getProxyUid()\npublic @java.lang.Deprecated @android.annotation.Nullable java.lang.String getProxyPackageName()\nprivate @android.app.UidState int getLastAccessUidStateForFlagsInStatesOfAllAttributions(int,int,int)\npublic @android.app.UidState int getLastAccessUidState(int)\npublic @android.app.UidState int getLastForegroundAccessUidState(int)\npublic @android.app.UidState int getLastBackgroundAccessUidState(int)\nprivate @android.app.UidState int getLastRejectUidStateForFlagsInStatesOfAllAttributions(int,int,int)\npublic @android.app.UidState int getLastRejectUidState(int)\npublic @android.app.UidState int getLastForegroundRejectUidState(int)\npublic @android.app.UidState int getLastBackgroundRejectUidState(int)\npublic long getDuration(int,int)\npublic int getProxyUid(int,int)\nprivate int getProxyUid(int,int,int)\npublic @android.annotation.Nullable java.lang.String getProxyPackageName(int,int)\nprivate @android.annotation.Nullable java.lang.String getProxyPackageName(int,int,int)\nclass OpEntry extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}
*/
@@ -4206,7 +4216,7 @@
void visitHistoricalOps(@NonNull HistoricalOps ops);
void visitHistoricalUidOps(@NonNull HistoricalUidOps ops);
void visitHistoricalPackageOps(@NonNull HistoricalPackageOps ops);
- void visitHistoricalFeatureOps(@NonNull HistoricalFeatureOps ops);
+ void visitHistoricalAttributionOps(@NonNull AttributedHistoricalOps ops);
void visitHistoricalOp(@NonNull HistoricalOp ops);
}
@@ -4219,7 +4229,7 @@
@IntDef(flag = true, prefix = { "FILTER_BY_" }, value = {
FILTER_BY_UID,
FILTER_BY_PACKAGE_NAME,
- FILTER_BY_FEATURE_ID,
+ FILTER_BY_ATTRIBUTION_TAG,
FILTER_BY_OP_NAMES
})
public @interface HistoricalOpsRequestFilter {}
@@ -4239,11 +4249,11 @@
public static final int FILTER_BY_PACKAGE_NAME = 1<<1;
/**
- * Filter historical appop request by feature id.
+ * Filter historical appop request by attribution tag.
*
* @hide
*/
- public static final int FILTER_BY_FEATURE_ID = 1<<2;
+ public static final int FILTER_BY_ATTRIBUTION_TAG = 1<<2;
/**
* Filter historical appop request by op names.
@@ -4264,7 +4274,7 @@
public static final class HistoricalOpsRequest {
private final int mUid;
private final @Nullable String mPackageName;
- private final @Nullable String mFeatureId;
+ private final @Nullable String mAttributionTag;
private final @Nullable List<String> mOpNames;
private final @HistoricalOpsRequestFilter int mFilter;
private final long mBeginTimeMillis;
@@ -4272,12 +4282,12 @@
private final @OpFlags int mFlags;
private HistoricalOpsRequest(int uid, @Nullable String packageName,
- @Nullable String featureId, @Nullable List<String> opNames,
+ @Nullable String attributionTag, @Nullable List<String> opNames,
@HistoricalOpsRequestFilter int filter, long beginTimeMillis,
long endTimeMillis, @OpFlags int flags) {
mUid = uid;
mPackageName = packageName;
- mFeatureId = featureId;
+ mAttributionTag = attributionTag;
mOpNames = opNames;
mFilter = filter;
mBeginTimeMillis = beginTimeMillis;
@@ -4295,7 +4305,7 @@
public static final class Builder {
private int mUid = Process.INVALID_UID;
private @Nullable String mPackageName;
- private @Nullable String mFeatureId;
+ private @Nullable String mAttributionTag;
private @Nullable List<String> mOpNames;
private @HistoricalOpsRequestFilter int mFilter;
private final long mBeginTimeMillis;
@@ -4359,14 +4369,14 @@
}
/**
- * Sets the feature id to query for.
+ * Sets the attribution tag to query for.
*
- * @param featureId The id of the feature.
+ * @param attributionTag attribution tag
* @return This builder.
*/
- public @NonNull Builder setFeatureId(@Nullable String featureId) {
- mFeatureId = featureId;
- mFilter |= FILTER_BY_FEATURE_ID;
+ public @NonNull Builder setAttributionTag(@Nullable String attributionTag) {
+ mAttributionTag = attributionTag;
+ mFilter |= FILTER_BY_ATTRIBUTION_TAG;
return this;
}
@@ -4417,7 +4427,7 @@
* @return a new {@link HistoricalOpsRequest}.
*/
public @NonNull HistoricalOpsRequest build() {
- return new HistoricalOpsRequest(mUid, mPackageName, mFeatureId, mOpNames,
+ return new HistoricalOpsRequest(mUid, mPackageName, mAttributionTag, mOpNames,
mFilter, mBeginTimeMillis, mEndTimeMillis, mFlags);
}
}
@@ -4577,7 +4587,7 @@
*
* @param uid Uid to filter for.
* @param packageName Package to filter for.
- * @param featureId Package to filter for.
+ * @param attributionTag attribution tag to filter for
* @param opNames Ops to filter for.
* @param filter Which parameters to filter on.
* @param beginTimeMillis The begin time to filter for or {@link Long#MIN_VALUE} for all.
@@ -4585,7 +4595,7 @@
*
* @hide
*/
- public void filter(int uid, @Nullable String packageName, @Nullable String featureId,
+ public void filter(int uid, @Nullable String packageName, @Nullable String attributionTag,
@Nullable String[] opNames, @HistoricalOpsRequestFilter int filter,
long beginTimeMillis, long endTimeMillis) {
final long durationMillis = getDurationMillis();
@@ -4599,7 +4609,7 @@
if ((filter & FILTER_BY_UID) != 0 && uid != uidOp.getUid()) {
mHistoricalUidOps.removeAt(i);
} else {
- uidOp.filter(packageName, featureId, opNames, filter, scaleFactor);
+ uidOp.filter(packageName, attributionTag, opNames, filter, scaleFactor);
if (uidOp.getPackageCount() == 0) {
mHistoricalUidOps.removeAt(i);
}
@@ -4630,28 +4640,28 @@
/** @hide */
@TestApi
public void increaseAccessCount(int opCode, int uid, @NonNull String packageName,
- @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags,
long increment) {
getOrCreateHistoricalUidOps(uid).increaseAccessCount(opCode,
- packageName, featureId, uidState, flags, increment);
+ packageName, attributionTag, uidState, flags, increment);
}
/** @hide */
@TestApi
public void increaseRejectCount(int opCode, int uid, @NonNull String packageName,
- @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags,
long increment) {
getOrCreateHistoricalUidOps(uid).increaseRejectCount(opCode,
- packageName, featureId, uidState, flags, increment);
+ packageName, attributionTag, uidState, flags, increment);
}
/** @hide */
@TestApi
public void increaseAccessDuration(int opCode, int uid, @NonNull String packageName,
- @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags,
long increment) {
getOrCreateHistoricalUidOps(uid).increaseAccessDuration(opCode,
- packageName, featureId, uidState, flags, increment);
+ packageName, attributionTag, uidState, flags, increment);
}
/** @hide */
@@ -4931,7 +4941,7 @@
}
}
- private void filter(@Nullable String packageName, @Nullable String featureId,
+ private void filter(@Nullable String packageName, @Nullable String attributionTag,
@Nullable String[] opNames, @HistoricalOpsRequestFilter int filter,
double fractionToRemove) {
final int packageCount = getPackageCount();
@@ -4941,8 +4951,8 @@
packageOps.getPackageName())) {
mHistoricalPackageOps.removeAt(i);
} else {
- packageOps.filter(featureId, opNames, filter, fractionToRemove);
- if (packageOps.getFeatureCount() == 0) {
+ packageOps.filter(attributionTag, opNames, filter, fractionToRemove);
+ if (packageOps.getAttributedOpsCount() == 0) {
mHistoricalPackageOps.removeAt(i);
}
}
@@ -4961,24 +4971,24 @@
}
private void increaseAccessCount(int opCode, @NonNull String packageName,
- @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags,
long increment) {
getOrCreateHistoricalPackageOps(packageName).increaseAccessCount(
- opCode, featureId, uidState, flags, increment);
+ opCode, attributionTag, uidState, flags, increment);
}
private void increaseRejectCount(int opCode, @NonNull String packageName,
- @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags,
long increment) {
getOrCreateHistoricalPackageOps(packageName).increaseRejectCount(
- opCode, featureId, uidState, flags, increment);
+ opCode, attributionTag, uidState, flags, increment);
}
private void increaseAccessDuration(int opCode, @NonNull String packageName,
- @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags,
long increment) {
getOrCreateHistoricalPackageOps(packageName).increaseAccessDuration(
- opCode, featureId, uidState, flags, increment);
+ opCode, attributionTag, uidState, flags, increment);
}
/**
@@ -5123,7 +5133,7 @@
@SystemApi
public static final class HistoricalPackageOps implements Parcelable {
private final @NonNull String mPackageName;
- private @Nullable ArrayMap<String, HistoricalFeatureOps> mHistoricalFeatureOps;
+ private @Nullable ArrayMap<String, AttributedHistoricalOps> mAttributedHistoricalOps;
/** @hide */
public HistoricalPackageOps(@NonNull String packageName) {
@@ -5132,70 +5142,71 @@
private HistoricalPackageOps(@NonNull HistoricalPackageOps other) {
mPackageName = other.mPackageName;
- final int opCount = other.getFeatureCount();
+ final int opCount = other.getAttributedOpsCount();
for (int i = 0; i < opCount; i++) {
- final HistoricalFeatureOps origOps = other.getFeatureOpsAt(i);
- final HistoricalFeatureOps cloneOps = new HistoricalFeatureOps(origOps);
- if (mHistoricalFeatureOps == null) {
- mHistoricalFeatureOps = new ArrayMap<>(opCount);
+ final AttributedHistoricalOps origOps = other.getAttributedOpsAt(i);
+ final AttributedHistoricalOps cloneOps = new AttributedHistoricalOps(origOps);
+ if (mAttributedHistoricalOps == null) {
+ mAttributedHistoricalOps = new ArrayMap<>(opCount);
}
- mHistoricalFeatureOps.put(cloneOps.getFeatureId(), cloneOps);
+ mAttributedHistoricalOps.put(cloneOps.getTag(), cloneOps);
}
}
private HistoricalPackageOps(@NonNull Parcel parcel) {
mPackageName = parcel.readString();
- mHistoricalFeatureOps = parcel.createTypedArrayMap(HistoricalFeatureOps.CREATOR);
+ mAttributedHistoricalOps = parcel.createTypedArrayMap(AttributedHistoricalOps.CREATOR);
}
private @Nullable HistoricalPackageOps splice(double fractionToRemove) {
HistoricalPackageOps splice = null;
- final int featureCount = getFeatureCount();
- for (int i = 0; i < featureCount; i++) {
- final HistoricalFeatureOps origOps = getFeatureOpsAt(i);
- final HistoricalFeatureOps spliceOps = origOps.splice(fractionToRemove);
+ final int attributionCount = getAttributedOpsCount();
+ for (int i = 0; i < attributionCount; i++) {
+ final AttributedHistoricalOps origOps = getAttributedOpsAt(i);
+ final AttributedHistoricalOps spliceOps = origOps.splice(fractionToRemove);
if (spliceOps != null) {
if (splice == null) {
splice = new HistoricalPackageOps(mPackageName);
}
- if (splice.mHistoricalFeatureOps == null) {
- splice.mHistoricalFeatureOps = new ArrayMap<>();
+ if (splice.mAttributedHistoricalOps == null) {
+ splice.mAttributedHistoricalOps = new ArrayMap<>();
}
- splice.mHistoricalFeatureOps.put(spliceOps.getFeatureId(), spliceOps);
+ splice.mAttributedHistoricalOps.put(spliceOps.getTag(), spliceOps);
}
}
return splice;
}
private void merge(@NonNull HistoricalPackageOps other) {
- final int featureCount = other.getFeatureCount();
- for (int i = 0; i < featureCount; i++) {
- final HistoricalFeatureOps otherFeatureOps = other.getFeatureOpsAt(i);
- final HistoricalFeatureOps thisFeatureOps = getFeatureOps(
- otherFeatureOps.getFeatureId());
- if (thisFeatureOps != null) {
- thisFeatureOps.merge(otherFeatureOps);
+ final int attributionCount = other.getAttributedOpsCount();
+ for (int i = 0; i < attributionCount; i++) {
+ final AttributedHistoricalOps otherAttributionOps = other.getAttributedOpsAt(i);
+ final AttributedHistoricalOps thisAttributionOps = getAttributedOps(
+ otherAttributionOps.getTag());
+ if (thisAttributionOps != null) {
+ thisAttributionOps.merge(otherAttributionOps);
} else {
- if (mHistoricalFeatureOps == null) {
- mHistoricalFeatureOps = new ArrayMap<>();
+ if (mAttributedHistoricalOps == null) {
+ mAttributedHistoricalOps = new ArrayMap<>();
}
- mHistoricalFeatureOps.put(otherFeatureOps.getFeatureId(), otherFeatureOps);
+ mAttributedHistoricalOps.put(otherAttributionOps.getTag(),
+ otherAttributionOps);
}
}
}
- private void filter(@Nullable String featureId, @Nullable String[] opNames,
+ private void filter(@Nullable String attributionTag, @Nullable String[] opNames,
@HistoricalOpsRequestFilter int filter, double fractionToRemove) {
- final int featureCount = getFeatureCount();
- for (int i = featureCount - 1; i >= 0; i--) {
- final HistoricalFeatureOps featureOps = getFeatureOpsAt(i);
- if ((filter & FILTER_BY_FEATURE_ID) != 0 && !Objects.equals(featureId,
- featureOps.getFeatureId())) {
- mHistoricalFeatureOps.removeAt(i);
+ final int attributionCount = getAttributedOpsCount();
+ for (int i = attributionCount - 1; i >= 0; i--) {
+ final AttributedHistoricalOps attributionOps = getAttributedOpsAt(i);
+ if ((filter & FILTER_BY_ATTRIBUTION_TAG) != 0 && !Objects.equals(attributionTag,
+ attributionOps.getTag())) {
+ mAttributedHistoricalOps.removeAt(i);
} else {
- featureOps.filter(opNames, filter, fractionToRemove);
- if (featureOps.getOpCount() == 0) {
- mHistoricalFeatureOps.removeAt(i);
+ attributionOps.filter(opNames, filter, fractionToRemove);
+ if (attributionOps.getOpCount() == 0) {
+ mAttributedHistoricalOps.removeAt(i);
}
}
}
@@ -5203,38 +5214,38 @@
private void accept(@NonNull HistoricalOpsVisitor visitor) {
visitor.visitHistoricalPackageOps(this);
- final int featureCount = getFeatureCount();
- for (int i = 0; i < featureCount; i++) {
- getFeatureOpsAt(i).accept(visitor);
+ final int attributionCount = getAttributedOpsCount();
+ for (int i = 0; i < attributionCount; i++) {
+ getAttributedOpsAt(i).accept(visitor);
}
}
private boolean isEmpty() {
- final int featureCount = getFeatureCount();
- for (int i = featureCount - 1; i >= 0; i--) {
- final HistoricalFeatureOps featureOps = mHistoricalFeatureOps.valueAt(i);
- if (!featureOps.isEmpty()) {
+ final int attributionCount = getAttributedOpsCount();
+ for (int i = attributionCount - 1; i >= 0; i--) {
+ final AttributedHistoricalOps attributionOps = mAttributedHistoricalOps.valueAt(i);
+ if (!attributionOps.isEmpty()) {
return false;
}
}
return true;
}
- private void increaseAccessCount(int opCode, @Nullable String featureId,
+ private void increaseAccessCount(int opCode, @Nullable String attributionTag,
@UidState int uidState, @OpFlags int flags, long increment) {
- getOrCreateHistoricalFeatureOps(featureId).increaseAccessCount(
+ getOrCreateAttributedHistoricalOps(attributionTag).increaseAccessCount(
opCode, uidState, flags, increment);
}
- private void increaseRejectCount(int opCode, @Nullable String featureId,
+ private void increaseRejectCount(int opCode, @Nullable String attributionTag,
@UidState int uidState, @OpFlags int flags, long increment) {
- getOrCreateHistoricalFeatureOps(featureId).increaseRejectCount(
+ getOrCreateAttributedHistoricalOps(attributionTag).increaseRejectCount(
opCode, uidState, flags, increment);
}
- private void increaseAccessDuration(int opCode, @Nullable String featureId,
+ private void increaseAccessDuration(int opCode, @Nullable String attributionTag,
@UidState int uidState, @OpFlags int flags, long increment) {
- getOrCreateHistoricalFeatureOps(featureId).increaseAccessDuration(
+ getOrCreateAttributedHistoricalOps(attributionTag).increaseAccessDuration(
opCode, uidState, flags, increment);
}
@@ -5247,17 +5258,18 @@
return mPackageName;
}
- private @NonNull HistoricalFeatureOps getOrCreateHistoricalFeatureOps(
- @Nullable String featureId) {
- if (mHistoricalFeatureOps == null) {
- mHistoricalFeatureOps = new ArrayMap<>();
+ private @NonNull AttributedHistoricalOps getOrCreateAttributedHistoricalOps(
+ @Nullable String attributionTag) {
+ if (mAttributedHistoricalOps == null) {
+ mAttributedHistoricalOps = new ArrayMap<>();
}
- HistoricalFeatureOps historicalFeatureOp = mHistoricalFeatureOps.get(featureId);
- if (historicalFeatureOp == null) {
- historicalFeatureOp = new HistoricalFeatureOps(featureId);
- mHistoricalFeatureOps.put(featureId, historicalFeatureOp);
+ AttributedHistoricalOps historicalAttributionOp = mAttributedHistoricalOps.get(
+ attributionTag);
+ if (historicalAttributionOp == null) {
+ historicalAttributionOp = new AttributedHistoricalOps(attributionTag);
+ mAttributedHistoricalOps.put(attributionTag, historicalAttributionOp);
}
- return historicalFeatureOp;
+ return historicalAttributionOp;
}
/**
@@ -5268,13 +5280,13 @@
*/
public @IntRange(from = 0) int getOpCount() {
int numOps = 0;
- int numFeatures = getFeatureCount();
+ int numAttributions = getAttributedOpsCount();
for (int code = 0; code < _NUM_OP; code++) {
String opName = opToPublicName(code);
- for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
- if (getFeatureOpsAt(featureNum).getOp(opName) != null) {
+ for (int attributionNum = 0; attributionNum < numAttributions; attributionNum++) {
+ if (getAttributedOpsAt(attributionNum).getOp(opName) != null) {
numOps++;
break;
}
@@ -5287,7 +5299,7 @@
/**
* Gets the historical op at a given index.
*
- * <p>This combines the counts from all features.
+ * <p>This combines the counts from all attributions.
*
* @param index The index to lookup.
* @return The op at the given index.
@@ -5295,13 +5307,13 @@
*/
public @NonNull HistoricalOp getOpAt(@IntRange(from = 0) int index) {
int numOpsFound = 0;
- int numFeatures = getFeatureCount();
+ int numAttributions = getAttributedOpsCount();
for (int code = 0; code < _NUM_OP; code++) {
String opName = opToPublicName(code);
- for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
- if (getFeatureOpsAt(featureNum).getOp(opName) != null) {
+ for (int attributionNum = 0; attributionNum < numAttributions; attributionNum++) {
+ if (getAttributedOpsAt(attributionNum).getOp(opName) != null) {
if (numOpsFound == index) {
return getOp(opName);
} else {
@@ -5318,25 +5330,25 @@
/**
* Gets the historical entry for a given op name.
*
- * <p>This combines the counts from all features.
+ * <p>This combines the counts from all attributions.
*
* @param opName The op name.
* @return The historical entry for that op name.
*/
public @Nullable HistoricalOp getOp(@NonNull String opName) {
- if (mHistoricalFeatureOps == null) {
+ if (mAttributedHistoricalOps == null) {
return null;
}
HistoricalOp combinedOp = null;
- int numFeatures = getFeatureCount();
- for (int i = 0; i < numFeatures; i++) {
- HistoricalOp featureOp = getFeatureOpsAt(i).getOp(opName);
- if (featureOp != null) {
+ int numAttributions = getAttributedOpsCount();
+ for (int i = 0; i < numAttributions; i++) {
+ HistoricalOp attributionOp = getAttributedOpsAt(i).getOp(opName);
+ if (attributionOp != null) {
if (combinedOp == null) {
- combinedOp = new HistoricalOp(featureOp);
+ combinedOp = new HistoricalOp(attributionOp);
} else {
- combinedOp.merge(featureOp);
+ combinedOp.merge(attributionOp);
}
}
}
@@ -5352,7 +5364,7 @@
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
parcel.writeString(mPackageName);
- parcel.writeTypedArrayMap(mHistoricalFeatureOps, flags);
+ parcel.writeTypedArrayMap(mAttributedHistoricalOps, flags);
}
public static final @android.annotation.NonNull Creator<HistoricalPackageOps> CREATOR =
@@ -5380,11 +5392,11 @@
if (!mPackageName.equals(other.mPackageName)) {
return false;
}
- if (mHistoricalFeatureOps == null) {
- if (other.mHistoricalFeatureOps != null) {
+ if (mAttributedHistoricalOps == null) {
+ if (other.mAttributedHistoricalOps != null) {
return false;
}
- } else if (!mHistoricalFeatureOps.equals(other.mHistoricalFeatureOps)) {
+ } else if (!mAttributedHistoricalOps.equals(other.mAttributedHistoricalOps)) {
return false;
}
return true;
@@ -5393,58 +5405,58 @@
@Override
public int hashCode() {
int result = mPackageName != null ? mPackageName.hashCode() : 0;
- result = 31 * result + (mHistoricalFeatureOps != null ? mHistoricalFeatureOps.hashCode()
- : 0);
+ result = 31 * result + (mAttributedHistoricalOps != null
+ ? mAttributedHistoricalOps.hashCode() : 0);
return result;
}
/**
- * Gets number of feature with historical ops.
+ * Gets number of attributed historical ops.
*
- * @return The number of feature with historical ops.
+ * @return The number of attribution with historical ops.
*
- * @see #getFeatureOpsAt(int)
+ * @see #getAttributedOpsAt(int)
*/
- public @IntRange(from = 0) int getFeatureCount() {
- if (mHistoricalFeatureOps == null) {
+ public @IntRange(from = 0) int getAttributedOpsCount() {
+ if (mAttributedHistoricalOps == null) {
return 0;
}
- return mHistoricalFeatureOps.size();
+ return mAttributedHistoricalOps.size();
}
/**
- * Gets the historical feature ops at a given index.
+ * Gets the attributed historical ops at a given index.
*
* @param index The index.
*
- * @return The historical feature ops at the given index.
+ * @return The historical attribution ops at the given index.
*
- * @see #getFeatureCount()
+ * @see #getAttributedOpsCount()
*/
- public @NonNull HistoricalFeatureOps getFeatureOpsAt(@IntRange(from = 0) int index) {
- if (mHistoricalFeatureOps == null) {
+ public @NonNull AttributedHistoricalOps getAttributedOpsAt(@IntRange(from = 0) int index) {
+ if (mAttributedHistoricalOps == null) {
throw new IndexOutOfBoundsException();
}
- return mHistoricalFeatureOps.valueAt(index);
+ return mAttributedHistoricalOps.valueAt(index);
}
/**
- * Gets the historical feature ops for a given feature.
+ * Gets the attributed historical ops for a given attribution tag.
*
- * @param featureId The feature id.
+ * @param attributionTag The attribution tag.
*
- * @return The historical ops for the feature.
+ * @return The historical ops for the attribution.
*/
- public @Nullable HistoricalFeatureOps getFeatureOps(@NonNull String featureId) {
- if (mHistoricalFeatureOps == null) {
+ public @Nullable AttributedHistoricalOps getAttributedOps(@NonNull String attributionTag) {
+ if (mAttributedHistoricalOps == null) {
return null;
}
- return mHistoricalFeatureOps.get(featureId);
+ return mAttributedHistoricalOps.get(attributionTag);
}
}
/**
- * This class represents historical app op information about a feature in a package.
+ * This class represents historical app op information about a attribution in a package.
*
* @hide
*/
@@ -5454,20 +5466,20 @@
@DataClass(genHiddenConstructor = true,
genEqualsHashCode = true, genHiddenCopyConstructor = true) */
@DataClass.Suppress("getHistoricalOps")
- public static final class HistoricalFeatureOps implements Parcelable {
- /** Id of the {@link Context#createFeatureContext feature} in the package */
- private final @Nullable String mFeatureId;
+ public static final class AttributedHistoricalOps implements Parcelable {
+ /** {@link Context#createAttributionContext attribution} tag */
+ private final @Nullable String mTag;
- /** Ops for this feature */
+ /** Ops for this attribution */
private @Nullable ArrayMap<String, HistoricalOp> mHistoricalOps;
/** @hide */
- public HistoricalFeatureOps(@NonNull String featureId) {
- mFeatureId = featureId;
+ public AttributedHistoricalOps(@NonNull String tag) {
+ mTag = tag;
}
- private HistoricalFeatureOps(@NonNull HistoricalFeatureOps other) {
- mFeatureId = other.mFeatureId;
+ private AttributedHistoricalOps(@NonNull AttributedHistoricalOps other) {
+ mTag = other.mTag;
final int opCount = other.getOpCount();
for (int i = 0; i < opCount; i++) {
final HistoricalOp origOp = other.getOpAt(i);
@@ -5479,15 +5491,15 @@
}
}
- private @Nullable HistoricalFeatureOps splice(double fractionToRemove) {
- HistoricalFeatureOps splice = null;
+ private @Nullable AttributedHistoricalOps splice(double fractionToRemove) {
+ AttributedHistoricalOps splice = null;
final int opCount = getOpCount();
for (int i = 0; i < opCount; i++) {
final HistoricalOp origOps = getOpAt(i);
final HistoricalOp spliceOps = origOps.splice(fractionToRemove);
if (spliceOps != null) {
if (splice == null) {
- splice = new HistoricalFeatureOps(mFeatureId, null);
+ splice = new AttributedHistoricalOps(mTag, null);
}
if (splice.mHistoricalOps == null) {
splice.mHistoricalOps = new ArrayMap<>();
@@ -5498,7 +5510,7 @@
return splice;
}
- private void merge(@NonNull HistoricalFeatureOps other) {
+ private void merge(@NonNull AttributedHistoricalOps other) {
final int opCount = other.getOpCount();
for (int i = 0; i < opCount; i++) {
final HistoricalOp otherOp = other.getOpAt(i);
@@ -5595,7 +5607,7 @@
}
private void accept(@NonNull HistoricalOpsVisitor visitor) {
- visitor.visitHistoricalFeatureOps(this);
+ visitor.visitHistoricalAttributionOps(this);
final int opCount = getOpCount();
for (int i = 0; i < opCount; i++) {
getOpAt(i).accept(visitor);
@@ -5631,46 +5643,46 @@
/**
- * Creates a new HistoricalFeatureOps.
+ * Creates a new HistoricalAttributionOps.
*
- * @param featureId
- * Id of the {@link Context#createFeatureContext feature} in the package
+ * @param tag
+ * {@link Context#createAttributionContext attribution} tag
* @param historicalOps
- * Ops for this feature
+ * Ops for this attribution
* @hide
*/
@DataClass.Generated.Member
- public HistoricalFeatureOps(
- @Nullable String featureId,
+ public AttributedHistoricalOps(
+ @Nullable String tag,
@Nullable ArrayMap<String,HistoricalOp> historicalOps) {
- this.mFeatureId = featureId;
+ this.mTag = tag;
this.mHistoricalOps = historicalOps;
// onConstructed(); // You can define this method to get a callback
}
/**
- * Id of the {@link Context#createFeatureContext feature} in the package
+ * {@link Context#createAttributionContext attribution} tag
*/
@DataClass.Generated.Member
- public @Nullable String getFeatureId() {
- return mFeatureId;
+ public @Nullable String getTag() {
+ return mTag;
}
@Override
@DataClass.Generated.Member
public boolean equals(@Nullable Object o) {
// You can override field equality logic by defining either of the methods like:
- // boolean fieldNameEquals(HistoricalFeatureOps other) { ... }
+ // boolean fieldNameEquals(HistoricalAttributionOps other) { ... }
// boolean fieldNameEquals(FieldType otherValue) { ... }
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@SuppressWarnings("unchecked")
- HistoricalFeatureOps that = (HistoricalFeatureOps) o;
+ AttributedHistoricalOps that = (AttributedHistoricalOps) o;
//noinspection PointlessBooleanExpression
return true
- && Objects.equals(mFeatureId, that.mFeatureId)
+ && Objects.equals(mTag, that.mTag)
&& Objects.equals(mHistoricalOps, that.mHistoricalOps);
}
@@ -5681,7 +5693,7 @@
// int fieldNameHashCode() { ... }
int _hash = 1;
- _hash = 31 * _hash + Objects.hashCode(mFeatureId);
+ _hash = 31 * _hash + Objects.hashCode(mTag);
_hash = 31 * _hash + Objects.hashCode(mHistoricalOps);
return _hash;
}
@@ -5693,10 +5705,10 @@
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
- if (mFeatureId != null) flg |= 0x1;
+ if (mTag != null) flg |= 0x1;
if (mHistoricalOps != null) flg |= 0x2;
dest.writeByte(flg);
- if (mFeatureId != null) dest.writeString(mFeatureId);
+ if (mTag != null) dest.writeString(mTag);
if (mHistoricalOps != null) dest.writeMap(mHistoricalOps);
}
@@ -5707,35 +5719,35 @@
/** @hide */
@SuppressWarnings({"unchecked", "RedundantCast"})
@DataClass.Generated.Member
- /* package-private */ HistoricalFeatureOps(@NonNull Parcel in) {
+ /* package-private */ AttributedHistoricalOps(@NonNull Parcel in) {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
byte flg = in.readByte();
- String featureId = (flg & 0x1) == 0 ? null : in.readString();
+ String attributionTag = (flg & 0x1) == 0 ? null : in.readString();
ArrayMap<String,HistoricalOp> historicalOps = null;
if ((flg & 0x2) != 0) {
historicalOps = new ArrayMap();
in.readMap(historicalOps, HistoricalOp.class.getClassLoader());
}
- this.mFeatureId = featureId;
+ this.mTag = attributionTag;
this.mHistoricalOps = historicalOps;
// onConstructed(); // You can define this method to get a callback
}
@DataClass.Generated.Member
- public static final @NonNull Parcelable.Creator<HistoricalFeatureOps> CREATOR
- = new Parcelable.Creator<HistoricalFeatureOps>() {
+ public static final @NonNull Parcelable.Creator<AttributedHistoricalOps> CREATOR
+ = new Parcelable.Creator<AttributedHistoricalOps>() {
@Override
- public HistoricalFeatureOps[] newArray(int size) {
- return new HistoricalFeatureOps[size];
+ public AttributedHistoricalOps[] newArray(int size) {
+ return new AttributedHistoricalOps[size];
}
@Override
- public HistoricalFeatureOps createFromParcel(@NonNull Parcel in) {
- return new HistoricalFeatureOps(in);
+ public AttributedHistoricalOps createFromParcel(@NonNull Parcel in) {
+ return new AttributedHistoricalOps(in);
}
};
@@ -5744,7 +5756,7 @@
time = 1578113234821L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/app/AppOpsManager.java",
- inputSignatures = "private final @android.annotation.Nullable java.lang.String mFeatureId\nprivate @android.annotation.Nullable android.util.ArrayMap<java.lang.String,android.app.HistoricalOp> mHistoricalOps\nprivate @android.annotation.Nullable android.app.HistoricalFeatureOps splice(double)\nprivate void merge(android.app.HistoricalFeatureOps)\nprivate void filter(java.lang.String[],int,double)\nprivate boolean isEmpty()\nprivate void increaseAccessCount(int,int,int,long)\nprivate void increaseRejectCount(int,int,int,long)\nprivate void increaseAccessDuration(int,int,int,long)\npublic @android.annotation.IntRange(from=0L) int getOpCount()\npublic @android.annotation.NonNull android.app.HistoricalOp getOpAt(int)\npublic @android.annotation.Nullable android.app.HistoricalOp getOp(java.lang.String)\nprivate void accept(android.app.HistoricalOpsVisitor)\nprivate @android.annotation.NonNull android.app.HistoricalOp getOrCreateHistoricalOp(int)\nclass HistoricalFeatureOps extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genEqualsHashCode=true, genHiddenCopyConstructor=true)")
+ inputSignatures = "private final @android.annotation.Nullable java.lang.String mAttributionTag\nprivate @android.annotation.Nullable android.util.ArrayMap<java.lang.String,android.app.HistoricalOp> mHistoricalOps\nprivate @android.annotation.Nullable android.app.HistoricalAttributionOps splice(double)\nprivate void merge(android.app.HistoricalAttributionOps)\nprivate void filter(java.lang.String[],int,double)\nprivate boolean isEmpty()\nprivate void increaseAccessCount(int,int,int,long)\nprivate void increaseRejectCount(int,int,int,long)\nprivate void increaseAccessDuration(int,int,int,long)\npublic @android.annotation.IntRange(from=0L) int getOpCount()\npublic @android.annotation.NonNull android.app.HistoricalOp getOpAt(int)\npublic @android.annotation.Nullable android.app.HistoricalOp getOp(java.lang.String)\nprivate void accept(android.app.HistoricalOpsVisitor)\nprivate @android.annotation.NonNull android.app.HistoricalOp getOrCreateHistoricalOp(int)\nclass HistoricalAttributionOps extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true, genEqualsHashCode=true, genHiddenCopyConstructor=true)")
@Deprecated
private void __metadata() {}
*/
@@ -6420,7 +6432,7 @@
Objects.requireNonNull(executor, "executor cannot be null");
Objects.requireNonNull(callback, "callback cannot be null");
try {
- mService.getHistoricalOps(request.mUid, request.mPackageName, request.mFeatureId,
+ mService.getHistoricalOps(request.mUid, request.mPackageName, request.mAttributionTag,
request.mOpNames, request.mFilter, request.mBeginTimeMillis,
request.mEndTimeMillis, request.mFlags, new RemoteCallback((result) -> {
final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS);
@@ -6460,8 +6472,9 @@
Objects.requireNonNull(callback, "callback cannot be null");
try {
mService.getHistoricalOpsFromDiskRaw(request.mUid, request.mPackageName,
- request.mFeatureId, request.mOpNames, request.mFilter, request.mBeginTimeMillis,
- request.mEndTimeMillis, request.mFlags, new RemoteCallback((result) -> {
+ request.mAttributionTag, request.mOpNames, request.mFilter,
+ request.mBeginTimeMillis, request.mEndTimeMillis, request.mFlags,
+ new RemoteCallback((result) -> {
final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS);
final long identity = Binder.clearCallingIdentity();
try {
@@ -6712,6 +6725,13 @@
};
mModeWatchers.put(callback, cb);
}
+
+ // See CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE
+ if (!Compatibility.isChangeEnabled(
+ CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE)) {
+ flags |= CALL_BACK_ON_SWITCHED_OP;
+ }
+
try {
mService.startWatchingModeWithFlags(op, packageName, flags, cb);
} catch (RemoteException e) {
@@ -7044,8 +7064,8 @@
* @param op The operation to note. One of the OPSTR_* constants.
* @param uid The user id of the application attempting to perform the operation.
* @param packageName The name of the application attempting to perform the operation.
- * @param featureId The {@link Context#createFeatureContext feature} in the package or {@code
- * null} for default feature
+ * @param attributionTag The {@link Context#createAttributionContext attribution tag} or {@code
+ * null} for default attribution
* @param message A message describing the reason the op was noted
*
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -7055,8 +7075,8 @@
* @throws SecurityException If the app has been configured to crash on this op.
*/
public int noteOp(@NonNull String op, int uid, @Nullable String packageName,
- @Nullable String featureId, @Nullable String message) {
- return noteOp(strOpToOp(op), uid, packageName, featureId, message);
+ @Nullable String attributionTag, @Nullable String message) {
+ return noteOp(strOpToOp(op), uid, packageName, attributionTag, message);
}
/**
@@ -7072,7 +7092,8 @@
* @param op The operation to note. One of the OP_* constants.
* @param uid The user id of the application attempting to perform the operation.
* @param packageName The name of the application attempting to perform the operation.
- * @param featureId The feature in the app or {@code null} for default feature
+ * @param attributionTag The {@link Context#createAttributionContext attribution tag} or {@code
+ * null} for default attribution
* @param message A message describing the reason the op was noted
*
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -7083,9 +7104,9 @@
*
* @hide
*/
- public int noteOp(int op, int uid, @Nullable String packageName, @Nullable String featureId,
- @Nullable String message) {
- final int mode = noteOpNoThrow(op, uid, packageName, featureId, message);
+ public int noteOp(int op, int uid, @Nullable String packageName,
+ @Nullable String attributionTag, @Nullable String message) {
+ final int mode = noteOpNoThrow(op, uid, packageName, attributionTag, message);
if (mode == MODE_ERRORED) {
throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
}
@@ -7120,8 +7141,8 @@
* @param op The operation to note. One of the OPSTR_* constants.
* @param uid The user id of the application attempting to perform the operation.
* @param packageName The name of the application attempting to perform the operation.
- * @param featureId The {@link Context#createFeatureContext feature} in the package or {@code
- * null} for default feature
+ * @param attributionTag The {@link Context#createAttributionContext attribution tag} or {@code
+ * null} for default attribution
* @param message A message describing the reason the op was noted
*
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -7129,8 +7150,8 @@
* causing the app to crash).
*/
public int noteOpNoThrow(@NonNull String op, int uid, @NonNull String packageName,
- @Nullable String featureId, @Nullable String message) {
- return noteOpNoThrow(strOpToOp(op), uid, packageName, featureId, message);
+ @Nullable String attributionTag, @Nullable String message) {
+ return noteOpNoThrow(strOpToOp(op), uid, packageName, attributionTag, message);
}
/**
@@ -7140,7 +7161,8 @@
* @param op The operation to note. One of the OP_* constants.
* @param uid The user id of the application attempting to perform the operation.
* @param packageName The name of the application attempting to perform the operation.
- * @param featureId The feature in the app or {@code null} for default feature
+ * @param attributionTag The {@link Context#createAttributionContext attribution tag} or {@code
+ * null} for default attribution
* @param message A message describing the reason the op was noted
*
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -7150,7 +7172,7 @@
* @hide
*/
public int noteOpNoThrow(int op, int uid, @Nullable String packageName,
- @Nullable String featureId, @Nullable String message) {
+ @Nullable String attributionTag, @Nullable String message) {
try {
collectNoteOpCallsForValidation(op);
int collectionMode = getNotedOpCollectionMode(uid, packageName, op);
@@ -7161,14 +7183,14 @@
}
}
- int mode = mService.noteOperation(op, uid, packageName, featureId,
+ int mode = mService.noteOperation(op, uid, packageName, attributionTag,
collectionMode == COLLECT_ASYNC, message);
if (mode == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
- collectNotedOpForSelf(op, featureId);
+ collectNotedOpForSelf(op, attributionTag);
} else if (collectionMode == COLLECT_SYNC) {
- collectNotedOpSync(op, featureId);
+ collectNotedOpSync(op, attributionTag);
}
}
@@ -7208,8 +7230,8 @@
* @param op The operation to note. One of the OP_* constants.
* @param proxiedPackageName The name of the application calling into the proxy application.
* @param proxiedUid The uid of the proxied application
- * @param proxiedFeatureId The feature in the proxied app or {@code null} for default
- * feature
+ * @param proxiedAttributionTag The proxied {@link Context#createAttributionContext
+ * attribution tag} or {@code null} for default attribution
* @param message A message describing the reason the op was noted
*
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or {@link #MODE_IGNORED}
@@ -7221,8 +7243,8 @@
* @hide
*/
public int noteProxyOp(int op, @Nullable String proxiedPackageName, int proxiedUid,
- @Nullable String proxiedFeatureId, @Nullable String message) {
- int mode = noteProxyOpNoThrow(op, proxiedPackageName, proxiedUid, proxiedFeatureId,
+ @Nullable String proxiedAttributionTag, @Nullable String message) {
+ int mode = noteProxyOpNoThrow(op, proxiedPackageName, proxiedUid, proxiedAttributionTag,
message);
if (mode == MODE_ERRORED) {
throw new SecurityException("Proxy package " + mContext.getOpPackageName()
@@ -7241,8 +7263,8 @@
* @param op The operation to note. One of the OPSTR_* constants.
* @param proxiedPackageName The name of the application calling into the proxy application.
* @param proxiedUid The uid of the proxied application
- * @param proxiedFeatureId The feature in the proxied app or {@code null} for default
- * feature
+ * @param proxiedAttributionTag The proxied {@link Context#createAttributionContext
+ * attribution tag} or {@code null} for default attribution
* @param message A message describing the reason the op was noted
*
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or {@link #MODE_IGNORED}
@@ -7252,8 +7274,8 @@
* op.
*/
public int noteProxyOp(@NonNull String op, @Nullable String proxiedPackageName, int proxiedUid,
- @Nullable String proxiedFeatureId, @Nullable String message) {
- return noteProxyOp(strOpToOp(op), proxiedPackageName, proxiedUid, proxiedFeatureId,
+ @Nullable String proxiedAttributionTag, @Nullable String message) {
+ return noteProxyOp(strOpToOp(op), proxiedPackageName, proxiedUid, proxiedAttributionTag,
message);
}
@@ -7284,14 +7306,14 @@
* @param op The op to note
* @param proxiedPackageName The package to note the op for
* @param proxiedUid The uid the package belongs to
- * @param proxiedFeatureId The feature in the proxied app or {@code null} for default
- * feature
+ * @param proxiedAttributionTag The proxied {@link Context#createAttributionContext
+ * attribution tag} or {@code null} for default attribution
* @param message A message describing the reason the op was noted
*/
public int noteProxyOpNoThrow(@NonNull String op, @Nullable String proxiedPackageName,
- int proxiedUid, @Nullable String proxiedFeatureId, @Nullable String message) {
+ int proxiedUid, @Nullable String proxiedAttributionTag, @Nullable String message) {
return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName, proxiedUid,
- proxiedFeatureId, message);
+ proxiedAttributionTag, message);
}
/**
@@ -7302,14 +7324,14 @@
* @param proxiedPackageName The package to note the op for or {@code null} if the op should be
* noted for the "android" package
* @param proxiedUid The uid the package belongs to
- * @param proxiedFeatureId The feature in the proxied app or {@code null} for default
- * feature
+ * @param proxiedAttributionTag The proxied {@link Context#createAttributionContext
+ * attribution tag} or {@code null} for default attribution
* @param message A message describing the reason the op was noted
*
* @hide
*/
public int noteProxyOpNoThrow(int op, @Nullable String proxiedPackageName, int proxiedUid,
- @Nullable String proxiedFeatureId, @Nullable String message) {
+ @Nullable String proxiedAttributionTag, @Nullable String message) {
int myUid = Process.myUid();
try {
@@ -7323,17 +7345,17 @@
}
int mode = mService.noteProxyOperation(op, proxiedUid, proxiedPackageName,
- proxiedFeatureId, myUid, mContext.getOpPackageName(),
- mContext.getFeatureId(), collectionMode == COLLECT_ASYNC, message);
+ proxiedAttributionTag, myUid, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), collectionMode == COLLECT_ASYNC, message);
if (mode == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
- collectNotedOpForSelf(op, proxiedFeatureId);
+ collectNotedOpForSelf(op, proxiedAttributionTag);
} else if (collectionMode == COLLECT_SYNC
// Only collect app-ops when the proxy is trusted
&& mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
myUid) == PackageManager.PERMISSION_GRANTED) {
- collectNotedOpSync(op, proxiedFeatureId);
+ collectNotedOpSync(op, proxiedAttributionTag);
}
}
@@ -7522,8 +7544,8 @@
* @param op The operation to start. One of the OPSTR_* constants.
* @param uid The user id of the application attempting to perform the operation.
* @param packageName The name of the application attempting to perform the operation.
- * @param featureId The {@link Context#createFeatureContext feature} in the package or {@code
- * null} for default feature
+ * @param attributionTag The {@link Context#createAttributionContext attribution tag} or
+ * {@code null} for default attribution
* @param message Description why op was started
*
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -7534,8 +7556,8 @@
* the package is not in the passed in UID.
*/
public int startOp(@NonNull String op, int uid, @Nullable String packageName,
- @Nullable String featureId, @Nullable String message) {
- return startOp(strOpToOp(op), uid, packageName, false, featureId, message);
+ @Nullable String attributionTag, @Nullable String message) {
+ return startOp(strOpToOp(op), uid, packageName, false, attributionTag, message);
}
/**
@@ -7544,7 +7566,8 @@
* @param op The operation to start. One of the OP_* constants.
* @param uid The user id of the application attempting to perform the operation.
* @param packageName The name of the application attempting to perform the operation.
- * @param featureId The feature in the app or {@code null} for default feature
+ * @param attributionTag The {@link Context#createAttributionContext attribution tag} or
+ * {@code null} for default attribution
* @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}.
* @param message Description why op was started
*
@@ -7558,8 +7581,8 @@
* @hide
*/
public int startOp(int op, int uid, @Nullable String packageName, boolean startIfModeDefault,
- @Nullable String featureId, @Nullable String message) {
- final int mode = startOpNoThrow(op, uid, packageName, startIfModeDefault, featureId,
+ @Nullable String attributionTag, @Nullable String message) {
+ final int mode = startOpNoThrow(op, uid, packageName, startIfModeDefault, attributionTag,
message);
if (mode == MODE_ERRORED) {
throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
@@ -7602,7 +7625,8 @@
* @param op The operation to start. One of the OP_* constants.
* @param uid The user id of the application attempting to perform the operation.
* @param packageName The name of the application attempting to perform the operation.
- * @param featureId The feature in the app or {@code null} for default feature
+ * @param attributionTag The {@link Context#createAttributionContext attribution tag} or
+ * {@code null} for default attribution
* @param message Description why op was started
*
* @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -7610,8 +7634,8 @@
* causing the app to crash).
*/
public int startOpNoThrow(@NonNull String op, int uid, @NonNull String packageName,
- @NonNull String featureId, @Nullable String message) {
- return startOpNoThrow(strOpToOp(op), uid, packageName, false, featureId, message);
+ @NonNull String attributionTag, @Nullable String message) {
+ return startOpNoThrow(strOpToOp(op), uid, packageName, false, attributionTag, message);
}
/**
@@ -7621,7 +7645,8 @@
* @param op The operation to start. One of the OP_* constants.
* @param uid The user id of the application attempting to perform the operation.
* @param packageName The name of the application attempting to perform the operation.
- * @param featureId The feature in the app or {@code null} for default feature
+ * @param attributionTag The {@link Context#createAttributionContext attribution tag} or
+ * {@code null} for default attribution
* @param startIfModeDefault Whether to start if mode is {@link #MODE_DEFAULT}.
* @param message Description why op was started
*
@@ -7632,7 +7657,7 @@
* @hide
*/
public int startOpNoThrow(int op, int uid, @NonNull String packageName,
- boolean startIfModeDefault, @Nullable String featureId, @Nullable String message) {
+ boolean startIfModeDefault, @Nullable String attributionTag, @Nullable String message) {
try {
collectNoteOpCallsForValidation(op);
int collectionMode = getNotedOpCollectionMode(uid, packageName, op);
@@ -7644,13 +7669,13 @@
}
int mode = mService.startOperation(getClientId(), op, uid, packageName,
- featureId, startIfModeDefault, collectionMode == COLLECT_ASYNC, message);
+ attributionTag, startIfModeDefault, collectionMode == COLLECT_ASYNC, message);
if (mode == MODE_ALLOWED) {
if (collectionMode == COLLECT_SELF) {
- collectNotedOpForSelf(op, featureId);
+ collectNotedOpForSelf(op, attributionTag);
} else if (collectionMode == COLLECT_SYNC) {
- collectNotedOpSync(op, featureId);
+ collectNotedOpSync(op, attributionTag);
}
}
@@ -7684,8 +7709,8 @@
* previously passed in when starting the operation.
*/
public void finishOp(@NonNull String op, int uid, @NonNull String packageName,
- @Nullable String featureId) {
- finishOp(strOpToOp(op), uid, packageName, featureId);
+ @Nullable String attributionTag) {
+ finishOp(strOpToOp(op), uid, packageName, attributionTag);
}
/**
@@ -7706,9 +7731,9 @@
* @hide
*/
public void finishOp(int op, int uid, @NonNull String packageName,
- @Nullable String featureId) {
+ @Nullable String attributionTag) {
try {
- mService.finishOperation(getClientId(), op, uid, packageName, featureId);
+ mService.finishOperation(getClientId(), op, uid, packageName, attributionTag);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -7819,15 +7844,15 @@
* Collect a noted op for the current process.
*
* @param op The noted op
- * @param featureId The feature the op is noted for
+ * @param attributionTag The attribution tag the op is noted for
*/
- private void collectNotedOpForSelf(int op, @Nullable String featureId) {
+ private void collectNotedOpForSelf(int op, @Nullable String attributionTag) {
synchronized (sLock) {
if (sOnOpNotedCallback != null) {
- sOnOpNotedCallback.onSelfNoted(new SyncNotedAppOp(op, featureId));
+ sOnOpNotedCallback.onSelfNoted(new SyncNotedAppOp(op, attributionTag));
}
}
- sMessageCollector.onSelfNoted(new SyncNotedAppOp(op, featureId));
+ sMessageCollector.onSelfNoted(new SyncNotedAppOp(op, attributionTag));
}
/**
@@ -7836,9 +7861,9 @@
* <p> Delivered to caller via {@link #prefixParcelWithAppOpsIfNeeded}
*
* @param op The noted op
- * @param featureId The feature the op is noted for
+ * @param attributionTag The attribution tag the op is noted for
*/
- private void collectNotedOpSync(int op, @Nullable String featureId) {
+ private void collectNotedOpSync(int op, @Nullable String attributionTag) {
// If this is inside of a two-way binder call:
// We are inside of a two-way binder call. Delivered to caller via
// {@link #prefixParcelWithAppOpsIfNeeded}
@@ -7848,16 +7873,16 @@
sAppOpsNotedInThisBinderTransaction.set(appOpsNoted);
}
- long[] appOpsNotedForFeature = appOpsNoted.get(featureId);
- if (appOpsNotedForFeature == null) {
- appOpsNotedForFeature = new long[2];
- appOpsNoted.put(featureId, appOpsNotedForFeature);
+ long[] appOpsNotedForAttribution = appOpsNoted.get(attributionTag);
+ if (appOpsNotedForAttribution == null) {
+ appOpsNotedForAttribution = new long[2];
+ appOpsNoted.put(attributionTag, appOpsNotedForAttribution);
}
if (op < 64) {
- appOpsNotedForFeature[0] |= 1L << op;
+ appOpsNotedForAttribution[0] |= 1L << op;
} else {
- appOpsNotedForFeature[1] |= 1L << (op - 64);
+ appOpsNotedForAttribution[1] |= 1L << (op - 64);
}
}
@@ -7938,10 +7963,10 @@
p.writeInt(Parcel.EX_HAS_NOTED_APPOPS_REPLY_HEADER);
- int numFeatureWithNotesAppOps = notedAppOps.size();
- p.writeInt(numFeatureWithNotesAppOps);
+ int numAttributionWithNotesAppOps = notedAppOps.size();
+ p.writeInt(numAttributionWithNotesAppOps);
- for (int i = 0; i < numFeatureWithNotesAppOps; i++) {
+ for (int i = 0; i < numAttributionWithNotesAppOps; i++) {
p.writeString(notedAppOps.keyAt(i));
p.writeLong(notedAppOps.valueAt(i)[0]);
p.writeLong(notedAppOps.valueAt(i)[1]);
@@ -7959,10 +7984,10 @@
* @hide
*/
public static void readAndLogNotedAppops(@NonNull Parcel p) {
- int numFeaturesWithNotedAppOps = p.readInt();
+ int numAttributionsWithNotedAppOps = p.readInt();
- for (int i = 0; i < numFeaturesWithNotedAppOps; i++) {
- String featureId = p.readString();
+ for (int i = 0; i < numAttributionsWithNotedAppOps; i++) {
+ String attributionTag = p.readString();
long[] rawNotedAppOps = new long[2];
rawNotedAppOps[0] = p.readLong();
rawNotedAppOps[1] = p.readLong();
@@ -7974,13 +7999,13 @@
for (int code = notedAppOps.nextSetBit(0); code != -1;
code = notedAppOps.nextSetBit(code + 1)) {
if (sOnOpNotedCallback != null) {
- sOnOpNotedCallback.onNoted(new SyncNotedAppOp(code, featureId));
+ sOnOpNotedCallback.onNoted(new SyncNotedAppOp(code, attributionTag));
}
}
}
for (int code = notedAppOps.nextSetBit(0); code != -1;
code = notedAppOps.nextSetBit(code + 1)) {
- sMessageCollector.onNoted(new SyncNotedAppOp(code, featureId));
+ sMessageCollector.onNoted(new SyncNotedAppOp(code, attributionTag));
}
}
}
diff --git a/core/java/android/app/AsyncNotedAppOp.java b/core/java/android/app/AsyncNotedAppOp.java
index 4d955db..b0c2762c 100644
--- a/core/java/android/app/AsyncNotedAppOp.java
+++ b/core/java/android/app/AsyncNotedAppOp.java
@@ -48,8 +48,8 @@
/** Uid that noted the op */
private final @IntRange(from = 0) int mNotingUid;
- /** {@link android.content.Context#createFeatureContext Feature} in the app */
- private final @Nullable String mFeatureId;
+ /** {@link android.content.Context#createAttributionContext attribution tag} */
+ private final @Nullable String mAttributionTag;
/** Message associated with the noteOp. This message is set by the app noting the op */
private final @NonNull String mMessage;
@@ -92,8 +92,8 @@
* Op that was noted
* @param notingUid
* Uid that noted the op
- * @param featureId
- * {@link android.content.Context#createFeatureContext Feature} in the app
+ * @param attributionTag
+ * {@link android.content.Context#createAttributionContext attribution tag}
* @param message
* Message associated with the noteOp. This message is set by the app noting the op
* @param time
@@ -104,7 +104,7 @@
public AsyncNotedAppOp(
@IntRange(from = 0) int opCode,
@IntRange(from = 0) int notingUid,
- @Nullable String featureId,
+ @Nullable String attributionTag,
@NonNull String message,
@CurrentTimeMillisLong long time) {
this.mOpCode = opCode;
@@ -115,7 +115,7 @@
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mNotingUid,
"from", 0);
- this.mFeatureId = featureId;
+ this.mAttributionTag = attributionTag;
this.mMessage = message;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mMessage);
@@ -135,11 +135,11 @@
}
/**
- * {@link android.content.Context#createFeatureContext Feature} in the app
+ * {@link android.content.Context#createAttributionContext attribution tag}
*/
@DataClass.Generated.Member
- public @Nullable String getFeatureId() {
- return mFeatureId;
+ public @Nullable String getAttributionTag() {
+ return mAttributionTag;
}
/**
@@ -173,7 +173,7 @@
return true
&& mOpCode == that.mOpCode
&& mNotingUid == that.mNotingUid
- && java.util.Objects.equals(mFeatureId, that.mFeatureId)
+ && java.util.Objects.equals(mAttributionTag, that.mAttributionTag)
&& java.util.Objects.equals(mMessage, that.mMessage)
&& mTime == that.mTime;
}
@@ -187,7 +187,7 @@
int _hash = 1;
_hash = 31 * _hash + mOpCode;
_hash = 31 * _hash + mNotingUid;
- _hash = 31 * _hash + java.util.Objects.hashCode(mFeatureId);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mAttributionTag);
_hash = 31 * _hash + java.util.Objects.hashCode(mMessage);
_hash = 31 * _hash + Long.hashCode(mTime);
return _hash;
@@ -200,11 +200,11 @@
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
- if (mFeatureId != null) flg |= 0x4;
+ if (mAttributionTag != null) flg |= 0x4;
dest.writeByte(flg);
dest.writeInt(mOpCode);
dest.writeInt(mNotingUid);
- if (mFeatureId != null) dest.writeString(mFeatureId);
+ if (mAttributionTag != null) dest.writeString(mAttributionTag);
dest.writeString(mMessage);
dest.writeLong(mTime);
}
@@ -223,7 +223,7 @@
byte flg = in.readByte();
int opCode = in.readInt();
int notingUid = in.readInt();
- String featureId = (flg & 0x4) == 0 ? null : in.readString();
+ String attributionTag = (flg & 0x4) == 0 ? null : in.readString();
String message = in.readString();
long time = in.readLong();
@@ -235,7 +235,7 @@
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mNotingUid,
"from", 0);
- this.mFeatureId = featureId;
+ this.mAttributionTag = attributionTag;
this.mMessage = message;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mMessage);
@@ -261,10 +261,10 @@
};
@DataClass.Generated(
- time = 1583866178330L,
+ time = 1583866239013L,
codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/app/AsyncNotedAppOp.java",
- inputSignatures = "private final @android.annotation.IntRange(from=0L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.CurrentTimeMillisLong long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nprivate void onConstructed()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
+ inputSignatures = "private final @android.annotation.IntRange(from=0L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mAttributionTag\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.CurrentTimeMillisLong long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nprivate void onConstructed()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 2873b10..56e6aee 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -219,8 +219,8 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final String mOpPackageName;
- /** If of feature this context is for */
- private final @Nullable String mFeatureId;
+ /** Attribution tag of this context */
+ private final @Nullable String mAttributionTag;
private final @NonNull ResourcesManager mResourcesManager;
@UnsupportedAppUsage
@@ -421,8 +421,8 @@
/** @hide */
@Override
- public @Nullable String getFeatureId() {
- return mFeatureId;
+ public @Nullable String getAttributionTag() {
+ return mAttributionTag;
}
@Override
@@ -1026,10 +1026,10 @@
public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
try {
ActivityTaskManager.getService().startActivityAsUser(
- mMainThread.getApplicationThread(), getBasePackageName(), getFeatureId(), intent,
- intent.resolveTypeIfNeeded(getContentResolver()),
- null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, options,
- user.getIdentifier());
+ mMainThread.getApplicationThread(), getBasePackageName(), getAttributionTag(),
+ intent, intent.resolveTypeIfNeeded(getContentResolver()),
+ null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, options,
+ user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1109,9 +1109,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
- getUserId());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false,
+ false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1126,9 +1126,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
- null, false, false, getUserId());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ null, Activity.RESULT_OK, null, null, receiverPermissions,
+ AppOpsManager.OP_NONE, null, false, false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1141,9 +1141,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
- null, false, false, getUserId());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ null, Activity.RESULT_OK, null, null, receiverPermissions,
+ AppOpsManager.OP_NONE, null, false, false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1156,9 +1156,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
- null, false, false, user.getIdentifier());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ null, Activity.RESULT_OK, null, null, receiverPermissions,
+ AppOpsManager.OP_NONE, null, false, false, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1173,9 +1173,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
- options, false, false, getUserId());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ null, Activity.RESULT_OK, null, null, receiverPermissions,
+ AppOpsManager.OP_NONE, options, false, false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1190,9 +1190,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false,
- getUserId());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ null, Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false,
+ false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1207,9 +1207,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
- null, true, false, getUserId());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ null, Activity.RESULT_OK, null, null, receiverPermissions,
+ AppOpsManager.OP_NONE, null, true, false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1270,8 +1270,8 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, rd,
- initialCode, initialData, initialExtras, receiverPermissions, appOp,
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ rd, initialCode, initialData, initialExtras, receiverPermissions, appOp,
options, true, false, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1284,9 +1284,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
- user.getIdentifier());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false,
+ false, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1307,9 +1307,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
- options, false, false, user.getIdentifier());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ null, Activity.RESULT_OK, null, null, receiverPermissions,
+ AppOpsManager.OP_NONE, options, false, false, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1324,9 +1324,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false, false,
- user.getIdentifier());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ null, Activity.RESULT_OK, null, null, receiverPermissions, appOp, null, false,
+ false, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1375,9 +1375,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, rd,
- initialCode, initialData, initialExtras, receiverPermissions,
- appOp, options, true, false, user.getIdentifier());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ rd, initialCode, initialData, initialExtras, receiverPermissions, appOp,
+ options, true, false, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1416,9 +1416,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, true,
- getUserId());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false,
+ true, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1452,9 +1452,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, rd,
- initialCode, initialData, initialExtras, null,
- AppOpsManager.OP_NONE, null, true, true, getUserId());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ rd, initialCode, initialData, initialExtras, null, AppOpsManager.OP_NONE, null,
+ true, true, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1484,9 +1484,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, true,
- user.getIdentifier());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false,
+ true, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1499,9 +1499,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, options, false, true,
- user.getIdentifier());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, options,
+ false, true, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1534,9 +1534,9 @@
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(
- mMainThread.getApplicationThread(), getFeatureId(), intent, resolvedType, rd,
- initialCode, initialData, initialExtras, null,
- AppOpsManager.OP_NONE, null, true, true, user.getIdentifier());
+ mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,
+ rd, initialCode, initialData, initialExtras, null, AppOpsManager.OP_NONE, null,
+ true, true, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1620,7 +1620,7 @@
}
try {
final Intent intent = ActivityManager.getService().registerReceiverWithFeature(
- mMainThread.getApplicationThread(), mBasePackageName, getFeatureId(), rd,
+ mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), rd,
filter, broadcastPermission, userId, flags);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
@@ -1696,7 +1696,7 @@
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
- getOpPackageName(), getFeatureId(), user.getIdentifier());
+ getOpPackageName(), getAttributionTag(), user.getIdentifier());
if (cn != null) {
if (cn.getPackageName().equals("!")) {
throw new SecurityException(
@@ -2285,14 +2285,14 @@
if (packageName.equals("system") || packageName.equals("android")) {
// The system resources are loaded in every application, so we can safely copy
// the context without reloading Resources.
- return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, null,
+ return new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag, null,
mToken, user, flags, null, null);
}
LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
if (pi != null) {
- ContextImpl c = new ContextImpl(this, mMainThread, pi, mFeatureId, null,
+ ContextImpl c = new ContextImpl(this, mMainThread, pi, mAttributionTag, null,
mToken, user, flags, null, null);
final int displayId = getDisplayId();
@@ -2329,7 +2329,7 @@
final String[] paths = mPackageInfo.getSplitPaths(splitName);
final ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo,
- mFeatureId, splitName, mToken, mUser, mFlags, classLoader, null);
+ mAttributionTag, splitName, mToken, mUser, mFlags, classLoader, null);
final int displayId = getDisplayId();
@@ -2353,7 +2353,7 @@
throw new IllegalArgumentException("overrideConfiguration must not be null");
}
- ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId,
+ ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag,
mSplitName, mToken, mUser, mFlags, mClassLoader, null);
final int displayId = getDisplayId();
@@ -2370,7 +2370,7 @@
throw new IllegalArgumentException("display must not be null");
}
- ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId,
+ ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag,
mSplitName, mToken, mUser, mFlags, mClassLoader, null);
final int displayId = display.getDisplayId();
@@ -2394,7 +2394,7 @@
}
ContextImpl createBaseWindowContext(IBinder token) {
- ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId,
+ ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag,
mSplitName, token, mUser, mFlags, mClassLoader, null);
context.mIsUiContext = true;
@@ -2420,8 +2420,8 @@
}
@Override
- public @NonNull Context createFeatureContext(@Nullable String featureId) {
- return new ContextImpl(this, mMainThread, mPackageInfo, featureId, mSplitName,
+ public @NonNull Context createAttributionContext(@Nullable String attributionTag) {
+ return new ContextImpl(this, mMainThread, mPackageInfo, attributionTag, mSplitName,
mToken, mUser, mFlags, mClassLoader, null);
}
@@ -2429,7 +2429,7 @@
public Context createDeviceProtectedStorageContext() {
final int flags = (mFlags & ~Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE)
| Context.CONTEXT_DEVICE_PROTECTED_STORAGE;
- return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName,
+ return new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag, mSplitName,
mToken, mUser, flags, mClassLoader, null);
}
@@ -2437,7 +2437,7 @@
public Context createCredentialProtectedStorageContext() {
final int flags = (mFlags & ~Context.CONTEXT_DEVICE_PROTECTED_STORAGE)
| Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE;
- return new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId, mSplitName,
+ return new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag, mSplitName,
mToken, mUser, flags, mClassLoader, null);
}
@@ -2700,7 +2700,7 @@
}
private ContextImpl(@Nullable ContextImpl container, @NonNull ActivityThread mainThread,
- @NonNull LoadedApk packageInfo, @Nullable String featureId,
+ @NonNull LoadedApk packageInfo, @Nullable String attributionTag,
@Nullable String splitName, @Nullable IBinder activityToken, @Nullable UserHandle user,
int flags, @Nullable ClassLoader classLoader, @Nullable String overrideOpPackageName) {
mOuterContext = this;
@@ -2754,7 +2754,7 @@
}
mOpPackageName = overrideOpPackageName != null ? overrideOpPackageName : opPackageName;
- mFeatureId = featureId;
+ mAttributionTag = attributionTag;
mContentResolver = new ApplicationContentResolver(this, mainThread);
}
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 34684c4..4cb8d93 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -175,11 +175,4 @@
* Called from SystemUI when it shows the AoD UI.
*/
oneway void setInAmbientMode(boolean inAmbientMode, long animationDuration);
-
- /**
- * Called when the wallpaper needs to zoom out.
- * The zoom value goes from 0 to 1 (inclusive) where 1 means fully zoomed out,
- * 0 means fully zoomed in
- */
- oneway void setWallpaperZoomOut(float zoom, String callingPackage, int displayId);
}
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 18932c6..818a121 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1720,11 +1720,10 @@
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
- int result = ActivityTaskManager.getService()
- .startActivity(whoThread, who.getBasePackageName(), who.getFeatureId(), intent,
- intent.resolveTypeIfNeeded(who.getContentResolver()),
- token, target != null ? target.mEmbeddedID : null,
- requestCode, 0, null, options);
+ int result = ActivityTaskManager.getService().startActivity(whoThread,
+ who.getBasePackageName(), who.getAttributionTag(), intent,
+ intent.resolveTypeIfNeeded(who.getContentResolver()), token,
+ target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
@@ -1793,9 +1792,9 @@
intents[i].prepareToLeaveProcess(who);
resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
}
- int result = ActivityTaskManager.getService()
- .startActivities(whoThread, who.getBasePackageName(), who.getFeatureId(), intents,
- resolvedTypes, token, options, userId);
+ int result = ActivityTaskManager.getService().startActivities(whoThread,
+ who.getBasePackageName(), who.getAttributionTag(), intents, resolvedTypes,
+ token, options, userId);
checkStartActivityResult(result, intents[0]);
return result;
} catch (RemoteException e) {
@@ -1860,10 +1859,10 @@
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
- int result = ActivityTaskManager.getService()
- .startActivity(whoThread, who.getBasePackageName(), who.getFeatureId(), intent,
- intent.resolveTypeIfNeeded(who.getContentResolver()),
- token, target, requestCode, 0, null, options);
+ int result = ActivityTaskManager.getService().startActivity(whoThread,
+ who.getBasePackageName(), who.getAttributionTag(), intent,
+ intent.resolveTypeIfNeeded(who.getContentResolver()), token, target,
+ requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
@@ -1927,11 +1926,10 @@
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
- int result = ActivityTaskManager.getService()
- .startActivityAsUser(whoThread, who.getBasePackageName(), who.getFeatureId(),
- intent, intent.resolveTypeIfNeeded(who.getContentResolver()),
- token, resultWho,
- requestCode, 0, null, options, user.getIdentifier());
+ int result = ActivityTaskManager.getService().startActivityAsUser(whoThread,
+ who.getBasePackageName(), who.getAttributionTag(), intent,
+ intent.resolveTypeIfNeeded(who.getContentResolver()), token, resultWho,
+ requestCode, 0, null, options, user.getIdentifier());
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
@@ -2022,7 +2020,7 @@
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(),
- who.getFeatureId(), intent,
+ who.getAttributionTag(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()), options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 3f2ec44..94b237c 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -134,6 +134,7 @@
* @hide
*/
@SystemApi
+ @TestApi
public static final int USER_LOCKED_SOUND = 0x00000020;
/**
@@ -331,6 +332,7 @@
/**
* @hide
*/
+ @TestApi
public void lockFields(int field) {
mUserLockedFields |= field;
}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index f68c929..792f840 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -355,8 +355,8 @@
intent.prepareToLeaveProcess(context);
IIntentSender target =
ActivityManager.getService().getIntentSenderWithFeature(
- ActivityManager.INTENT_SENDER_ACTIVITY, packageName, context.getFeatureId(),
- null, null, requestCode, new Intent[] { intent },
+ ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
+ context.getAttributionTag(), null, null, requestCode, new Intent[] { intent },
resolvedType != null ? new String[] { resolvedType } : null,
flags, options, context.getUserId());
return target != null ? new PendingIntent(target) : null;
@@ -381,8 +381,8 @@
intent.prepareToLeaveProcess(context);
IIntentSender target =
ActivityManager.getService().getIntentSenderWithFeature(
- ActivityManager.INTENT_SENDER_ACTIVITY, packageName, context.getFeatureId(),
- null, null, requestCode, new Intent[] { intent },
+ ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
+ context.getAttributionTag(), null, null, requestCode, new Intent[] { intent },
resolvedType != null ? new String[] { resolvedType } : null,
flags, options, user.getIdentifier());
return target != null ? new PendingIntent(target) : null;
@@ -498,9 +498,9 @@
try {
IIntentSender target =
ActivityManager.getService().getIntentSenderWithFeature(
- ActivityManager.INTENT_SENDER_ACTIVITY, packageName, context.getFeatureId(),
- null, null, requestCode, intents, resolvedTypes, flags, options,
- context.getUserId());
+ ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
+ context.getAttributionTag(), null, null, requestCode, intents, resolvedTypes,
+ flags, options, context.getUserId());
return target != null ? new PendingIntent(target) : null;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -524,8 +524,8 @@
try {
IIntentSender target =
ActivityManager.getService().getIntentSenderWithFeature(
- ActivityManager.INTENT_SENDER_ACTIVITY, packageName, context.getFeatureId(),
- null, null, requestCode, intents, resolvedTypes,
+ ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
+ context.getAttributionTag(), null, null, requestCode, intents, resolvedTypes,
flags, options, user.getIdentifier());
return target != null ? new PendingIntent(target) : null;
} catch (RemoteException e) {
@@ -576,8 +576,8 @@
intent.prepareToLeaveProcess(context);
IIntentSender target =
ActivityManager.getService().getIntentSenderWithFeature(
- ActivityManager.INTENT_SENDER_BROADCAST, packageName, context.getFeatureId(),
- null, null, requestCode, new Intent[] { intent },
+ ActivityManager.INTENT_SENDER_BROADCAST, packageName,
+ context.getAttributionTag(), null, null, requestCode, new Intent[] { intent },
resolvedType != null ? new String[] { resolvedType } : null,
flags, null, userHandle.getIdentifier());
return target != null ? new PendingIntent(target) : null;
@@ -655,7 +655,7 @@
intent.prepareToLeaveProcess(context);
IIntentSender target =
ActivityManager.getService().getIntentSenderWithFeature(
- serviceKind, packageName, context.getFeatureId(),
+ serviceKind, packageName, context.getAttributionTag(),
null, null, requestCode, new Intent[] { intent },
resolvedType != null ? new String[] { resolvedType } : null,
flags, null, context.getUserId());
diff --git a/core/java/android/app/RuntimeAppOpAccessMessage.java b/core/java/android/app/RuntimeAppOpAccessMessage.java
index a81b8e7..a19f815 100644
--- a/core/java/android/app/RuntimeAppOpAccessMessage.java
+++ b/core/java/android/app/RuntimeAppOpAccessMessage.java
@@ -44,7 +44,7 @@
/** Name of package for which runtime app op access message was collected */
private final @NonNull String mPackageName;
/** Feature of package for which runtime app op access message was collected */
- private final @Nullable String mFeatureId;
+ private final @Nullable String mAttributionTag;
/** Message collected (including stacktrace for synchronous ops) */
private final @NonNull String mMessage;
/** Sampling strategy used to collect this message. */
@@ -63,8 +63,8 @@
* Op code of operation access which was collected
* @param packageName
* Name of package for which runtime app op access message was collected
- * @param featureId
- * Feature of package for which runtime app op access message was collected
+ * @param attributionTag
+ * Attribution tag for which runtime app op access message was collected
* @param message
* Message collected (including stacktrace for synchronous ops)
* @param samplingStrategy
@@ -75,7 +75,7 @@
@IntRange(from = 0L) int uid,
@IntRange(from = 0L) int opCode,
@NonNull String packageName,
- @Nullable String featureId,
+ @Nullable String attributionTag,
@NonNull String message,
@AppOpsManager.SamplingStrategy int samplingStrategy) {
this.mUid = uid;
@@ -90,7 +90,7 @@
this.mPackageName = packageName;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mPackageName);
- this.mFeatureId = featureId;
+ this.mAttributionTag = attributionTag;
this.mMessage = message;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mMessage);
@@ -134,11 +134,11 @@
}
/**
- * Feature of package for which runtime app op access message was collected
+ * Attribution tag for which runtime app op access message was collected
*/
@DataClass.Generated.Member
- public @Nullable String getFeatureId() {
- return mFeatureId;
+ public @Nullable String getAttributionTag() {
+ return mAttributionTag;
}
/**
@@ -164,12 +164,12 @@
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
- if (mFeatureId != null) flg |= 0x8;
+ if (mAttributionTag != null) flg |= 0x8;
dest.writeByte(flg);
dest.writeInt(mUid);
dest.writeInt(mOpCode);
dest.writeString(mPackageName);
- if (mFeatureId != null) dest.writeString(mFeatureId);
+ if (mAttributionTag != null) dest.writeString(mAttributionTag);
dest.writeString(mMessage);
dest.writeInt(mSamplingStrategy);
}
@@ -189,7 +189,7 @@
int uid = in.readInt();
int opCode = in.readInt();
String packageName = in.readString();
- String featureId = (flg & 0x8) == 0 ? null : in.readString();
+ String attributionTag = (flg & 0x8) == 0 ? null : in.readString();
String message = in.readString();
int samplingStrategy = in.readInt();
@@ -205,7 +205,7 @@
this.mPackageName = packageName;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mPackageName);
- this.mFeatureId = featureId;
+ this.mAttributionTag = attributionTag;
this.mMessage = message;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mMessage);
@@ -234,7 +234,7 @@
time = 1581517099127L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/app/RuntimeAppOpAccessMessage.java",
- inputSignatures = "private final @android.annotation.IntRange(from=0L) int mUid\nprivate final @android.annotation.IntRange(from=0L, to=AppOpsManager._NUM_OP - 1) int mOpCode\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.app.AppOpsManager.SamplingStrategy int mSamplingStrategy\npublic @android.annotation.NonNull java.lang.String getOp()\nclass RuntimeAppOpAccessMessage extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false)")*/
+ inputSignatures = "private final @android.annotation.IntRange(from=0L) int mUid\nprivate final @android.annotation.IntRange(from=0L, to=AppOpsManager._NUM_OP - 1) int mOpCode\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mAttributionTag\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.app.AppOpsManager.SamplingStrategy int mSamplingStrategy\npublic @android.annotation.NonNull java.lang.String getOp()\nclass RuntimeAppOpAccessMessage extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false)")*/
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/app/SyncNotedAppOp.java b/core/java/android/app/SyncNotedAppOp.java
index 13b90ca..0a880dc 100644
--- a/core/java/android/app/SyncNotedAppOp.java
+++ b/core/java/android/app/SyncNotedAppOp.java
@@ -43,24 +43,24 @@
/** op code of synchronous appop noted */
private final @IntRange(from = 0L, to = AppOpsManager._NUM_OP - 1) int mOpCode;
- /** featureId of synchronous appop noted */
- private final @Nullable String mFeatureId;
+ /** attributionTag of synchronous appop noted */
+ private final @Nullable String mAttributionTag;
/**
* Creates a new SyncNotedAppOp.
*
* @param opCode
* op code of synchronous appop noted
- * @param featureId
- * featureId of synchronous appop noted
+ * @param attributionTag
+ * attributionTag of synchronous appop noted
*/
- public SyncNotedAppOp(@IntRange(from = 0L) int opCode, @Nullable String featureId) {
+ public SyncNotedAppOp(@IntRange(from = 0L) int opCode, @Nullable String attributionTag) {
this.mOpCode = opCode;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mOpCode,
"from", 0,
"to", AppOpsManager._NUM_OP - 1);
- this.mFeatureId = featureId;
+ this.mAttributionTag = attributionTag;
}
/**
@@ -84,11 +84,11 @@
/**
- * featureId of synchronous appop noted
+ * attributionTag of synchronous appop noted
*/
@DataClass.Generated.Member
- public @Nullable String getFeatureId() {
- return mFeatureId;
+ public @Nullable String getAttributionTag() {
+ return mAttributionTag;
}
@Override
@@ -105,7 +105,7 @@
//noinspection PointlessBooleanExpression
return true
&& mOpCode == that.mOpCode
- && java.util.Objects.equals(mFeatureId, that.mFeatureId);
+ && java.util.Objects.equals(mAttributionTag, that.mAttributionTag);
}
@Override
@@ -116,7 +116,7 @@
int _hash = 1;
_hash = 31 * _hash + mOpCode;
- _hash = 31 * _hash + java.util.Objects.hashCode(mFeatureId);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mAttributionTag);
return _hash;
}
@@ -127,10 +127,10 @@
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
- if (mFeatureId != null) flg |= 0x2;
+ if (mAttributionTag != null) flg |= 0x2;
dest.writeByte(flg);
dest.writeInt(mOpCode);
- if (mFeatureId != null) dest.writeString(mFeatureId);
+ if (mAttributionTag != null) dest.writeString(mAttributionTag);
}
@Override
@@ -146,14 +146,14 @@
byte flg = in.readByte();
int opCode = in.readInt();
- String featureId = (flg & 0x2) == 0 ? null : in.readString();
+ String attributionTag = (flg & 0x2) == 0 ? null : in.readString();
this.mOpCode = opCode;
com.android.internal.util.AnnotationValidations.validate(
IntRange.class, null, mOpCode,
"from", 0,
"to", AppOpsManager._NUM_OP - 1);
- this.mFeatureId = featureId;
+ this.mAttributionTag = attributionTag;
// onConstructed(); // You can define this method to get a callback
}
@@ -176,7 +176,7 @@
time = 1579188889960L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/app/SyncNotedAppOp.java",
- inputSignatures = "private final @android.annotation.IntRange(from=0L, to=AppOpsManager._NUM_OP - 1) int mOpCode\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\npublic @android.annotation.NonNull java.lang.String getOp()\npublic @android.annotation.SystemApi int getOpCode()\nclass SyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genConstructor=false)")*/
+ inputSignatures = "private final @android.annotation.IntRange(from=0L, to=AppOpsManager._NUM_OP - 1) int mOpCode\nprivate final @android.annotation.Nullable java.lang.String mAttributionTag\npublic @android.annotation.NonNull java.lang.String getOp()\npublic @android.annotation.SystemApi int getOpCode()\nclass SyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genConstructor=false)")*/
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index d9405e1..1b1568a 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -478,7 +478,7 @@
try {
Bundle params = new Bundle();
ParcelFileDescriptor pfd = mService.getWallpaperWithFeature(
- context.getOpPackageName(), context.getFeatureId(), this, FLAG_SYSTEM,
+ context.getOpPackageName(), context.getAttributionTag(), this, FLAG_SYSTEM,
params, userId);
if (pfd != null) {
@@ -1069,7 +1069,7 @@
try {
Bundle outParams = new Bundle();
return sGlobals.mService.getWallpaperWithFeature(mContext.getOpPackageName(),
- mContext.getFeatureId(), null, which, outParams, userId);
+ mContext.getAttributionTag(), null, which, outParams, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (SecurityException e) {
@@ -1858,13 +1858,12 @@
*
* @hide
*/
- public void setWallpaperZoomOut(float zoom) {
+ public void setWallpaperZoomOut(IBinder windowToken, float zoom) {
if (zoom < 0 || zoom > 1f) {
throw new IllegalArgumentException("zoom must be between 0 and one: " + zoom);
}
try {
- sGlobals.mService.setWallpaperZoomOut(zoom, mContext.getOpPackageName(),
- mContext.getDisplayId());
+ WindowManagerGlobal.getWindowSession().setWallpaperZoomOut(windowToken, zoom);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index c532279..8895a02 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6001,7 +6001,7 @@
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param required Whether auto time is set required or not.
* @throws SecurityException if {@code admin} is not a device owner.
- * @deprecated From {@link android.os.Build.VERSION_CODES#R}. Use {@link #setAutoTime}
+ * @deprecated From {@link android.os.Build.VERSION_CODES#R}. Use {@link #setAutoTimeEnabled}
* to turn auto time on or off and use {@link UserManager#DISALLOW_CONFIG_DATE_TIME}
* to prevent the user from changing this setting.
*/
@@ -6019,7 +6019,7 @@
/**
* @return true if auto time is required.
- * @deprecated From {@link android.os.Build.VERSION_CODES#R}. Use {@link #getAutoTime}
+ * @deprecated From {@link android.os.Build.VERSION_CODES#R}. Use {@link #getAutoTimeEnabled}
*/
@Deprecated
public boolean getAutoTimeRequired() {
@@ -6049,10 +6049,10 @@
* @throws SecurityException if caller is not a device owner, a profile owner for the
* primary user, or a profile owner of an organization-owned managed profile.
*/
- public void setAutoTime(@NonNull ComponentName admin, boolean enabled) {
+ public void setAutoTimeEnabled(@NonNull ComponentName admin, boolean enabled) {
if (mService != null) {
try {
- mService.setAutoTime(admin, enabled);
+ mService.setAutoTimeEnabled(admin, enabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -6064,10 +6064,10 @@
* @throws SecurityException if caller is not a device owner, a profile owner for the
* primary user, or a profile owner of an organization-owned managed profile.
*/
- public boolean getAutoTime(@NonNull ComponentName admin) {
+ public boolean getAutoTimeEnabled(@NonNull ComponentName admin) {
if (mService != null) {
try {
- return mService.getAutoTime(admin);
+ return mService.getAutoTimeEnabled(admin);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -6090,11 +6090,11 @@
* @throws SecurityException if caller is not a device owner, a profile owner for the
* primary user, or a profile owner of an organization-owned managed profile.
*/
- public void setAutoTimeZone(@NonNull ComponentName admin, boolean enabled) {
+ public void setAutoTimeZoneEnabled(@NonNull ComponentName admin, boolean enabled) {
throwIfParentInstance("setAutoTimeZone");
if (mService != null) {
try {
- mService.setAutoTimeZone(admin, enabled);
+ mService.setAutoTimeZoneEnabled(admin, enabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -6106,11 +6106,11 @@
* @throws SecurityException if caller is not a device owner, a profile owner for the
* primary user, or a profile owner of an organization-owned managed profile.
*/
- public boolean getAutoTimeZone(@NonNull ComponentName admin) {
+ public boolean getAutoTimeZoneEnabled(@NonNull ComponentName admin) {
throwIfParentInstance("getAutoTimeZone");
if (mService != null) {
try {
- return mService.getAutoTimeZone(admin);
+ return mService.getAutoTimeZoneEnabled(admin);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -11984,17 +11984,17 @@
* must handle this intent.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with
- * @param timeoutMs Maximum time the profile is allowed to be off in milliseconds or 0 if
+ * @param timeoutMillis Maximum time the profile is allowed to be off in milliseconds or 0 if
* not limited.
* @throws IllegalStateException if the profile owner doesn't have an activity that handles
* {@link #ACTION_CHECK_POLICY_COMPLIANCE}
* @see #setPersonalAppsSuspended
*/
- public void setManagedProfileMaximumTimeOff(@NonNull ComponentName admin, long timeoutMs) {
+ public void setManagedProfileMaximumTimeOff(@NonNull ComponentName admin, long timeoutMillis) {
throwIfParentInstance("setManagedProfileMaximumTimeOff");
if (mService != null) {
try {
- mService.setManagedProfileMaximumTimeOff(admin, timeoutMs);
+ mService.setManagedProfileMaximumTimeOff(admin, timeoutMillis);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index da48663..f071239 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -308,11 +308,11 @@
void setAutoTimeRequired(in ComponentName who, boolean required);
boolean getAutoTimeRequired();
- void setAutoTime(in ComponentName who, boolean enabled);
- boolean getAutoTime(in ComponentName who);
+ void setAutoTimeEnabled(in ComponentName who, boolean enabled);
+ boolean getAutoTimeEnabled(in ComponentName who);
- void setAutoTimeZone(in ComponentName who, boolean enabled);
- boolean getAutoTimeZone(in ComponentName who);
+ void setAutoTimeZoneEnabled(in ComponentName who, boolean enabled);
+ boolean getAutoTimeZoneEnabled(in ComponentName who);
void setForceEphemeralUsers(in ComponentName who, boolean forceEpehemeralUsers);
boolean getForceEphemeralUsers(in ComponentName who);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 6ae68fc..608b563 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -849,7 +849,7 @@
synchronized (mLock) {
if (sBluetoothLeScanner == null) {
sBluetoothLeScanner = new BluetoothLeScanner(mManagerService, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
}
}
return sBluetoothLeScanner;
@@ -1663,11 +1663,11 @@
return ActivityThread.currentOpPackageName();
}
- private String getFeatureId() {
+ private String getAttributionTag() {
// Workaround for legacy API for getting a BluetoothAdapter not
// passing a context
if (mContext != null) {
- return mContext.getFeatureId();
+ return mContext.getAttributionTag();
}
return null;
}
@@ -1709,7 +1709,7 @@
try {
mServiceLock.readLock().lock();
if (mService != null) {
- return mService.startDiscovery(getOpPackageName(), getFeatureId());
+ return mService.startDiscovery(getOpPackageName(), getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "", e);
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index 7ff6466..3b4fe0a 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -62,7 +62,7 @@
* @hide
*/
public BluetoothManager(Context context) {
- if (context.getFeatureId() == null) {
+ if (context.getAttributionTag() == null) {
context = context.getApplicationContext();
if (context == null) {
throw new IllegalArgumentException(
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index bd3298c..d8e8b27 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -230,12 +230,12 @@
}
@Override
- public Cursor query(String callingPkg, @Nullable String featureId, Uri uri,
+ public Cursor query(String callingPkg, @Nullable String attributionTag, Uri uri,
@Nullable String[] projection, @Nullable Bundle queryArgs,
@Nullable ICancellationSignal cancellationSignal) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, featureId, uri, null)
+ if (enforceReadPermission(callingPkg, attributionTag, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
// The caller has no access to the data, so return an empty cursor with
// the columns in the requested order. The caller may ask for an invalid
@@ -253,7 +253,7 @@
// columns. We then use the column names to return an empty cursor.
Cursor cursor;
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
cursor = mInterface.query(
uri, projection, queryArgs,
@@ -272,7 +272,7 @@
}
Trace.traceBegin(TRACE_TAG_DATABASE, "query");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return mInterface.query(
uri, projection, queryArgs,
@@ -308,15 +308,15 @@
}
@Override
- public Uri insert(String callingPkg, @Nullable String featureId, Uri uri,
+ public Uri insert(String callingPkg, @Nullable String attributionTag, Uri uri,
ContentValues initialValues, Bundle extras) {
uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, featureId, uri, null)
+ if (enforceWritePermission(callingPkg, attributionTag, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return rejectInsert(uri, initialValues);
} finally {
@@ -325,7 +325,7 @@
}
Trace.traceBegin(TRACE_TAG_DATABASE, "insert");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return maybeAddUserId(mInterface.insert(uri, initialValues, extras), userId);
} catch (RemoteException e) {
@@ -337,17 +337,17 @@
}
@Override
- public int bulkInsert(String callingPkg, @Nullable String featureId, Uri uri,
+ public int bulkInsert(String callingPkg, @Nullable String attributionTag, Uri uri,
ContentValues[] initialValues) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, featureId, uri, null)
+ if (enforceWritePermission(callingPkg, attributionTag, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
return 0;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "bulkInsert");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return mInterface.bulkInsert(uri, initialValues);
} catch (RemoteException e) {
@@ -359,8 +359,9 @@
}
@Override
- public ContentProviderResult[] applyBatch(String callingPkg, @Nullable String featureId,
- String authority, ArrayList<ContentProviderOperation> operations)
+ public ContentProviderResult[] applyBatch(String callingPkg,
+ @Nullable String attributionTag, String authority,
+ ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
validateIncomingAuthority(authority);
int numOperations = operations.size();
@@ -377,13 +378,13 @@
operations.set(i, operation);
}
if (operation.isReadOperation()) {
- if (enforceReadPermission(callingPkg, featureId, uri, null)
+ if (enforceReadPermission(callingPkg, attributionTag, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
throw new OperationApplicationException("App op not allowed", 0);
}
}
if (operation.isWriteOperation()) {
- if (enforceWritePermission(callingPkg, featureId, uri, null)
+ if (enforceWritePermission(callingPkg, attributionTag, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
throw new OperationApplicationException("App op not allowed", 0);
}
@@ -391,7 +392,7 @@
}
Trace.traceBegin(TRACE_TAG_DATABASE, "applyBatch");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
ContentProviderResult[] results = mInterface.applyBatch(authority,
operations);
@@ -413,16 +414,17 @@
}
@Override
- public int delete(String callingPkg, @Nullable String featureId, Uri uri, Bundle extras) {
+ public int delete(String callingPkg, @Nullable String attributionTag, Uri uri,
+ Bundle extras) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, featureId, uri, null)
+ if (enforceWritePermission(callingPkg, attributionTag, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
return 0;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "delete");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return mInterface.delete(uri, extras);
} catch (RemoteException e) {
@@ -434,17 +436,17 @@
}
@Override
- public int update(String callingPkg, @Nullable String featureId, Uri uri,
+ public int update(String callingPkg, @Nullable String attributionTag, Uri uri,
ContentValues values, Bundle extras) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, featureId, uri, null)
+ if (enforceWritePermission(callingPkg, attributionTag, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
return 0;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "update");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return mInterface.update(uri, values, extras);
} catch (RemoteException e) {
@@ -456,15 +458,15 @@
}
@Override
- public ParcelFileDescriptor openFile(String callingPkg, @Nullable String featureId,
+ public ParcelFileDescriptor openFile(String callingPkg, @Nullable String attributionTag,
Uri uri, String mode, ICancellationSignal cancellationSignal, IBinder callerToken)
throws FileNotFoundException {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- enforceFilePermission(callingPkg, featureId, uri, mode, callerToken);
+ enforceFilePermission(callingPkg, attributionTag, uri, mode, callerToken);
Trace.traceBegin(TRACE_TAG_DATABASE, "openFile");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return mInterface.openFile(
uri, mode, CancellationSignal.fromTransport(cancellationSignal));
@@ -477,15 +479,15 @@
}
@Override
- public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String featureId,
+ public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String attributionTag,
Uri uri, String mode, ICancellationSignal cancellationSignal)
throws FileNotFoundException {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- enforceFilePermission(callingPkg, featureId, uri, mode, null);
+ enforceFilePermission(callingPkg, attributionTag, uri, mode, null);
Trace.traceBegin(TRACE_TAG_DATABASE, "openAssetFile");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return mInterface.openAssetFile(
uri, mode, CancellationSignal.fromTransport(cancellationSignal));
@@ -498,13 +500,13 @@
}
@Override
- public Bundle call(String callingPkg, @Nullable String featureId, String authority,
+ public Bundle call(String callingPkg, @Nullable String attributionTag, String authority,
String method, @Nullable String arg, @Nullable Bundle extras) {
validateIncomingAuthority(authority);
Bundle.setDefusable(extras, true);
Trace.traceBegin(TRACE_TAG_DATABASE, "call");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return mInterface.call(authority, method, arg, extras);
} catch (RemoteException e) {
@@ -532,15 +534,15 @@
@Override
public AssetFileDescriptor openTypedAssetFile(String callingPkg,
- @Nullable String featureId, Uri uri, String mimeType, Bundle opts,
+ @Nullable String attributionTag, Uri uri, String mimeType, Bundle opts,
ICancellationSignal cancellationSignal) throws FileNotFoundException {
Bundle.setDefusable(opts, true);
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- enforceFilePermission(callingPkg, featureId, uri, "r", null);
+ enforceFilePermission(callingPkg, attributionTag, uri, "r", null);
Trace.traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return mInterface.openTypedAssetFile(
uri, mimeType, opts, CancellationSignal.fromTransport(cancellationSignal));
@@ -558,17 +560,17 @@
}
@Override
- public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri) {
+ public Uri canonicalize(String callingPkg, @Nullable String attributionTag, Uri uri) {
uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, featureId, uri, null)
+ if (enforceReadPermission(callingPkg, attributionTag, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
return null;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "canonicalize");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return maybeAddUserId(mInterface.canonicalize(uri), userId);
} catch (RemoteException e) {
@@ -580,26 +582,26 @@
}
@Override
- public void canonicalizeAsync(String callingPkg, @Nullable String featureId, Uri uri,
+ public void canonicalizeAsync(String callingPkg, @Nullable String attributionTag, Uri uri,
RemoteCallback callback) {
final Bundle result = new Bundle();
result.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
- canonicalize(callingPkg, featureId, uri));
+ canonicalize(callingPkg, attributionTag, uri));
callback.sendResult(result);
}
@Override
- public Uri uncanonicalize(String callingPkg, String featureId, Uri uri) {
+ public Uri uncanonicalize(String callingPkg, String attributionTag, Uri uri) {
uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, featureId, uri, null)
+ if (enforceReadPermission(callingPkg, attributionTag, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
return null;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "uncanonicalize");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return maybeAddUserId(mInterface.uncanonicalize(uri), userId);
} catch (RemoteException e) {
@@ -611,17 +613,17 @@
}
@Override
- public boolean refresh(String callingPkg, String featureId, Uri uri, Bundle extras,
+ public boolean refresh(String callingPkg, String attributionTag, Uri uri, Bundle extras,
ICancellationSignal cancellationSignal) throws RemoteException {
uri = validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, featureId, uri, null)
+ if (enforceReadPermission(callingPkg, attributionTag, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
return false;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "refresh");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return mInterface.refresh(uri, extras,
CancellationSignal.fromTransport(cancellationSignal));
@@ -632,13 +634,13 @@
}
@Override
- public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri,
+ public int checkUriPermission(String callingPkg, @Nullable String attributionTag, Uri uri,
int uid, int modeFlags) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
Trace.traceBegin(TRACE_TAG_DATABASE, "checkUriPermission");
final Pair<String, String> original = setCallingPackage(
- new Pair<>(callingPkg, featureId));
+ new Pair<>(callingPkg, attributionTag));
try {
return mInterface.checkUriPermission(uri, uid, modeFlags);
} catch (RemoteException e) {
@@ -649,47 +651,50 @@
}
}
- private void enforceFilePermission(String callingPkg, @Nullable String featureId, Uri uri,
- String mode, IBinder callerToken) throws FileNotFoundException, SecurityException {
+ private void enforceFilePermission(String callingPkg, @Nullable String attributionTag,
+ Uri uri, String mode, IBinder callerToken)
+ throws FileNotFoundException, SecurityException {
if (mode != null && mode.indexOf('w') != -1) {
- if (enforceWritePermission(callingPkg, featureId, uri, callerToken)
+ if (enforceWritePermission(callingPkg, attributionTag, uri, callerToken)
!= AppOpsManager.MODE_ALLOWED) {
throw new FileNotFoundException("App op not allowed");
}
} else {
- if (enforceReadPermission(callingPkg, featureId, uri, callerToken)
+ if (enforceReadPermission(callingPkg, attributionTag, uri, callerToken)
!= AppOpsManager.MODE_ALLOWED) {
throw new FileNotFoundException("App op not allowed");
}
}
}
- private int enforceReadPermission(String callingPkg, @Nullable String featureId, Uri uri,
- IBinder callerToken)
+ private int enforceReadPermission(String callingPkg, @Nullable String attributionTag,
+ Uri uri, IBinder callerToken)
throws SecurityException {
- final int mode = enforceReadPermissionInner(uri, callingPkg, featureId, callerToken);
+ final int mode = enforceReadPermissionInner(uri, callingPkg, attributionTag,
+ callerToken);
if (mode != MODE_ALLOWED) {
return mode;
}
- return noteProxyOp(callingPkg, featureId, mReadOp);
+ return noteProxyOp(callingPkg, attributionTag, mReadOp);
}
- private int enforceWritePermission(String callingPkg, String featureId, Uri uri,
+ private int enforceWritePermission(String callingPkg, String attributionTag, Uri uri,
IBinder callerToken)
throws SecurityException {
- final int mode = enforceWritePermissionInner(uri, callingPkg, featureId, callerToken);
+ final int mode = enforceWritePermissionInner(uri, callingPkg, attributionTag,
+ callerToken);
if (mode != MODE_ALLOWED) {
return mode;
}
- return noteProxyOp(callingPkg, featureId, mWriteOp);
+ return noteProxyOp(callingPkg, attributionTag, mWriteOp);
}
- private int noteProxyOp(String callingPkg, String featureId, int op) {
+ private int noteProxyOp(String callingPkg, String attributionTag, int op) {
if (op != AppOpsManager.OP_NONE) {
int mode = mAppOpsManager.noteProxyOp(op, callingPkg, Binder.getCallingUid(),
- featureId, null);
+ attributionTag, null);
return mode == MODE_DEFAULT ? MODE_IGNORED : mode;
}
@@ -711,19 +716,19 @@
* associated with that permission.
*/
private int checkPermissionAndAppOp(String permission, String callingPkg,
- @Nullable String featureId, IBinder callerToken) {
+ @Nullable String attributionTag, IBinder callerToken) {
if (getContext().checkPermission(permission, Binder.getCallingPid(), Binder.getCallingUid(),
callerToken) != PERMISSION_GRANTED) {
return MODE_ERRORED;
}
- return mTransport.noteProxyOp(callingPkg, featureId,
+ return mTransport.noteProxyOp(callingPkg, attributionTag,
AppOpsManager.permissionToOpCode(permission));
}
/** {@hide} */
protected int enforceReadPermissionInner(Uri uri, String callingPkg,
- @Nullable String featureId, IBinder callerToken) throws SecurityException {
+ @Nullable String attributionTag, IBinder callerToken) throws SecurityException {
final Context context = getContext();
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
@@ -737,7 +742,7 @@
if (mExported && checkUser(pid, uid, context)) {
final String componentPerm = getReadPermission();
if (componentPerm != null) {
- final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, featureId,
+ final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, attributionTag,
callerToken);
if (mode == MODE_ALLOWED) {
return MODE_ALLOWED;
@@ -757,8 +762,8 @@
for (PathPermission pp : pps) {
final String pathPerm = pp.getReadPermission();
if (pathPerm != null && pp.match(path)) {
- final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, featureId,
- callerToken);
+ final int mode = checkPermissionAndAppOp(pathPerm, callingPkg,
+ attributionTag, callerToken);
if (mode == MODE_ALLOWED) {
return MODE_ALLOWED;
} else {
@@ -807,7 +812,7 @@
/** {@hide} */
protected int enforceWritePermissionInner(Uri uri, String callingPkg,
- @Nullable String featureId, IBinder callerToken) throws SecurityException {
+ @Nullable String attributionTag, IBinder callerToken) throws SecurityException {
final Context context = getContext();
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
@@ -821,8 +826,8 @@
if (mExported && checkUser(pid, uid, context)) {
final String componentPerm = getWritePermission();
if (componentPerm != null) {
- final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, featureId,
- callerToken);
+ final int mode = checkPermissionAndAppOp(componentPerm, callingPkg,
+ attributionTag, callerToken);
if (mode == MODE_ALLOWED) {
return MODE_ALLOWED;
} else {
@@ -841,8 +846,8 @@
for (PathPermission pp : pps) {
final String pathPerm = pp.getWritePermission();
if (pathPerm != null && pp.match(path)) {
- final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, featureId,
- callerToken);
+ final int mode = checkPermissionAndAppOp(pathPerm, callingPkg,
+ attributionTag, callerToken);
if (mode == MODE_ALLOWED) {
return MODE_ALLOWED;
} else {
@@ -943,16 +948,16 @@
}
/**
- * Return the feature in the package of the caller that initiated the request being
+ * Return the attribution tag of the caller that initiated the request being
* processed on the current thread. Returns {@code null} if not currently processing
- * a request of the request is for the default feature.
+ * a request of the request is for the default attribution.
* <p>
* This will always return {@code null} when processing
* {@link #getType(Uri)} or {@link #getStreamTypes(Uri, String)} requests.
*
* @see #getCallingPackage
*/
- public final @Nullable String getCallingFeatureId() {
+ public final @Nullable String getCallingAttributionTag() {
final Pair<String, String> pkg = mCallingPackage.get();
if (pkg != null) {
return pkg.second;
@@ -962,6 +967,14 @@
}
/**
+ * @removed
+ */
+ @Deprecated
+ public final @Nullable String getCallingFeatureId() {
+ return getCallingAttributionTag();
+ }
+
+ /**
* Return the package name of the caller that initiated the request being
* processed on the current thread. The returned package will have
* <em>not</em> been verified to belong to the calling UID. Returns
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index a9b7862..d0f5ec4 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -80,7 +80,7 @@
private final IContentProvider mContentProvider;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final String mPackageName;
- private final @Nullable String mFeatureId;
+ private final @Nullable String mAttributionTag;
private final String mAuthority;
private final boolean mStable;
@@ -104,7 +104,7 @@
mContentResolver = contentResolver;
mContentProvider = contentProvider;
mPackageName = contentResolver.mPackageName;
- mFeatureId = contentResolver.mFeatureId;
+ mAttributionTag = contentResolver.mAttributionTag;
mAuthority = authority;
mStable = stable;
@@ -195,7 +195,8 @@
cancellationSignal.setRemote(remoteCancellationSignal);
}
final Cursor cursor = mContentProvider.query(
- mPackageName, mFeatureId, uri, projection, queryArgs, remoteCancellationSignal);
+ mPackageName, mAttributionTag, uri, projection, queryArgs,
+ remoteCancellationSignal);
if (cursor == null) {
return null;
}
@@ -255,7 +256,7 @@
beforeRemote();
try {
- return mContentProvider.canonicalize(mPackageName, mFeatureId, url);
+ return mContentProvider.canonicalize(mPackageName, mAttributionTag, url);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -273,7 +274,7 @@
beforeRemote();
try {
- return mContentProvider.uncanonicalize(mPackageName, mFeatureId, url);
+ return mContentProvider.uncanonicalize(mPackageName, mAttributionTag, url);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -298,7 +299,7 @@
remoteCancellationSignal = mContentProvider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- return mContentProvider.refresh(mPackageName, mFeatureId, url, extras,
+ return mContentProvider.refresh(mPackageName, mAttributionTag, url, extras,
remoteCancellationSignal);
} catch (DeadObjectException e) {
if (!mStable) {
@@ -318,7 +319,7 @@
beforeRemote();
try {
- return mContentProvider.checkUriPermission(mPackageName, mFeatureId, uri, uid,
+ return mContentProvider.checkUriPermission(mPackageName, mAttributionTag, uri, uid,
modeFlags);
} catch (DeadObjectException e) {
if (!mStable) {
@@ -344,7 +345,8 @@
beforeRemote();
try {
- return mContentProvider.insert(mPackageName, mFeatureId, url, initialValues, extras);
+ return mContentProvider.insert(mPackageName, mAttributionTag, url, initialValues,
+ extras);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -364,7 +366,7 @@
beforeRemote();
try {
- return mContentProvider.bulkInsert(mPackageName, mFeatureId, url, initialValues);
+ return mContentProvider.bulkInsert(mPackageName, mAttributionTag, url, initialValues);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -388,7 +390,7 @@
beforeRemote();
try {
- return mContentProvider.delete(mPackageName, mFeatureId, url, extras);
+ return mContentProvider.delete(mPackageName, mAttributionTag, url, extras);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -413,7 +415,7 @@
beforeRemote();
try {
- return mContentProvider.update(mPackageName, mFeatureId, url, values, extras);
+ return mContentProvider.update(mPackageName, mAttributionTag, url, values, extras);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -457,8 +459,8 @@
remoteSignal = mContentProvider.createCancellationSignal();
signal.setRemote(remoteSignal);
}
- return mContentProvider.openFile(mPackageName, mFeatureId, url, mode, remoteSignal,
- null);
+ return mContentProvider.openFile(mPackageName, mAttributionTag, url, mode,
+ remoteSignal, null);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -502,7 +504,7 @@
remoteSignal = mContentProvider.createCancellationSignal();
signal.setRemote(remoteSignal);
}
- return mContentProvider.openAssetFile(mPackageName, mFeatureId, url, mode,
+ return mContentProvider.openAssetFile(mPackageName, mAttributionTag, url, mode,
remoteSignal);
} catch (DeadObjectException e) {
if (!mStable) {
@@ -544,7 +546,7 @@
signal.setRemote(remoteSignal);
}
return mContentProvider.openTypedAssetFile(
- mPackageName, mFeatureId, uri, mimeTypeFilter, opts, remoteSignal);
+ mPackageName, mAttributionTag, uri, mimeTypeFilter, opts, remoteSignal);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -571,7 +573,8 @@
beforeRemote();
try {
- return mContentProvider.applyBatch(mPackageName, mFeatureId, authority, operations);
+ return mContentProvider.applyBatch(mPackageName, mAttributionTag, authority,
+ operations);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -597,7 +600,8 @@
beforeRemote();
try {
- return mContentProvider.call(mPackageName, mFeatureId, authority, method, arg, extras);
+ return mContentProvider.call(mPackageName, mAttributionTag, authority, method, arg,
+ extras);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 31e1fc8..b134c37 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -767,7 +767,7 @@
public ContentResolver(@Nullable Context context, @Nullable ContentInterface wrapped) {
mContext = context != null ? context : ActivityThread.currentApplication();
mPackageName = mContext.getOpPackageName();
- mFeatureId = mContext.getFeatureId();
+ mAttributionTag = mContext.getAttributionTag();
mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
mWrapped = wrapped;
}
@@ -1144,7 +1144,7 @@
cancellationSignal.setRemote(remoteCancellationSignal);
}
try {
- qCursor = unstableProvider.query(mPackageName, mFeatureId, uri, projection,
+ qCursor = unstableProvider.query(mPackageName, mAttributionTag, uri, projection,
queryArgs, remoteCancellationSignal);
} catch (DeadObjectException e) {
// The remote process has died... but we only hold an unstable
@@ -1155,7 +1155,7 @@
if (stableProvider == null) {
return null;
}
- qCursor = stableProvider.query(mPackageName, mFeatureId, uri, projection,
+ qCursor = stableProvider.query(mPackageName, mAttributionTag, uri, projection,
queryArgs, remoteCancellationSignal);
}
if (qCursor == null) {
@@ -1247,7 +1247,7 @@
try {
final UriResultListener resultListener = new UriResultListener();
- provider.canonicalizeAsync(mPackageName, mFeatureId, url,
+ provider.canonicalizeAsync(mPackageName, mAttributionTag, url,
new RemoteCallback(resultListener));
resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
return resultListener.result;
@@ -1294,7 +1294,7 @@
}
try {
- return provider.uncanonicalize(mPackageName, mFeatureId, url);
+ return provider.uncanonicalize(mPackageName, mAttributionTag, url);
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
// Manager will kill this process shortly anyway.
@@ -1346,7 +1346,7 @@
remoteCancellationSignal = provider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- return provider.refresh(mPackageName, mFeatureId, url, extras,
+ return provider.refresh(mPackageName, mAttributionTag, url, extras,
remoteCancellationSignal);
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
@@ -1748,7 +1748,8 @@
try {
fd = unstableProvider.openAssetFile(
- mPackageName, mFeatureId, uri, mode, remoteCancellationSignal);
+ mPackageName, mAttributionTag, uri, mode,
+ remoteCancellationSignal);
if (fd == null) {
// The provider will be released by the finally{} clause
return null;
@@ -1763,7 +1764,7 @@
throw new FileNotFoundException("No content provider: " + uri);
}
fd = stableProvider.openAssetFile(
- mPackageName, mFeatureId, uri, mode, remoteCancellationSignal);
+ mPackageName, mAttributionTag, uri, mode, remoteCancellationSignal);
if (fd == null) {
// The provider will be released by the finally{} clause
return null;
@@ -1914,7 +1915,8 @@
try {
fd = unstableProvider.openTypedAssetFile(
- mPackageName, mFeatureId, uri, mimeType, opts, remoteCancellationSignal);
+ mPackageName, mAttributionTag, uri, mimeType, opts,
+ remoteCancellationSignal);
if (fd == null) {
// The provider will be released by the finally{} clause
return null;
@@ -1929,7 +1931,8 @@
throw new FileNotFoundException("No content provider: " + uri);
}
fd = stableProvider.openTypedAssetFile(
- mPackageName, mFeatureId, uri, mimeType, opts, remoteCancellationSignal);
+ mPackageName, mAttributionTag, uri, mimeType, opts,
+ remoteCancellationSignal);
if (fd == null) {
// The provider will be released by the finally{} clause
return null;
@@ -2077,7 +2080,7 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- Uri createdRow = provider.insert(mPackageName, mFeatureId, url, values, extras);
+ Uri createdRow = provider.insert(mPackageName, mAttributionTag, url, values, extras);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
return createdRow;
@@ -2158,7 +2161,7 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- int rowsCreated = provider.bulkInsert(mPackageName, mFeatureId, url, values);
+ int rowsCreated = provider.bulkInsert(mPackageName, mAttributionTag, url, values);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */);
return rowsCreated;
@@ -2217,7 +2220,7 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- int rowsDeleted = provider.delete(mPackageName, mFeatureId, url, extras);
+ int rowsDeleted = provider.delete(mPackageName, mAttributionTag, url, extras);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, url, "delete", null);
return rowsDeleted;
@@ -2284,7 +2287,7 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- int rowsUpdated = provider.update(mPackageName, mFeatureId, uri, values, extras);
+ int rowsUpdated = provider.update(mPackageName, mAttributionTag, uri, values, extras);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, uri, "update", null);
return rowsUpdated;
@@ -2333,7 +2336,7 @@
throw new IllegalArgumentException("Unknown authority " + authority);
}
try {
- final Bundle res = provider.call(mPackageName, mFeatureId, authority, method, arg,
+ final Bundle res = provider.call(mPackageName, mAttributionTag, authority, method, arg,
extras);
Bundle.setDefusable(res, true);
return res;
@@ -3746,8 +3749,8 @@
}
/** @hide */
- public @Nullable String getFeatureId() {
- return mFeatureId;
+ public @Nullable String getAttributionTag() {
+ return mAttributionTag;
}
@UnsupportedAppUsage
@@ -3757,7 +3760,7 @@
@UnsupportedAppUsage
final String mPackageName;
- final @Nullable String mFeatureId;
+ final @Nullable String mAttributionTag;
final int mTargetSdkVersion;
final ContentInterface mWrapped;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 6cba327..318ae11 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -71,6 +71,7 @@
import android.view.View;
import android.view.ViewDebug;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams.WindowType;
import android.view.autofill.AutofillManager.AutofillClient;
import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
import android.view.textclassifier.TextClassificationManager;
@@ -814,16 +815,25 @@
}
/**
- * <p>Features are used in complex apps to logically separate parts of the app. E.g. a
- * blogging app might also have a instant messaging app built in.
+ * <p>Attribution can be used in complex apps to logically separate parts of the app. E.g. a
+ * blogging app might also have a instant messaging app built in. In this case two separate tags
+ * can for used each sub-feature.
*
- * @return the feature id this context is for or {@code null} if this is the default
- * feature.
+ * @return the attribution tag this context is for or {@code null} if this is the default.
*/
- public @Nullable String getFeatureId() {
+ public @Nullable String getAttributionTag() {
return null;
}
+ // TODO moltmann: Remove
+ /**
+ * @removed
+ */
+ @Deprecated
+ public @Nullable String getFeatureId() {
+ return getAttributionTag();
+ }
+
/** Return the full application info for this context's package. */
public abstract ApplicationInfo getApplicationInfo();
@@ -5820,24 +5830,34 @@
* @see #WALLPAPER_SERVICE
* @throws IllegalArgumentException if token is invalid
*/
- public @NonNull Context createWindowContext(int type, @Nullable Bundle options) {
+ public @NonNull Context createWindowContext(@WindowType int type, @Nullable Bundle options) {
throw new RuntimeException("Not implemented. Must override in a subclass.");
}
/**
- * Return a new Context object for the current Context but for a different feature in the app.
- * Features can be used by complex apps to separate logical parts.
+ * Return a new Context object for the current Context but attribute to a different tag.
+ * In complex apps attribution tagging can be used to distinguish between separate logical
+ * parts.
*
- * @param featureId The feature id or {@code null} to create a context for the default feature.
+ * @param attributionTag The tag or {@code null} to create a context for the default.
*
- * @return A {@link Context} for the feature
+ * @return A {@link Context} that is tagged for the new attribution
*
- * @see #getFeatureId()
+ * @see #getAttributionTag()
*/
- public @NonNull Context createFeatureContext(@Nullable String featureId) {
+ public @NonNull Context createAttributionContext(@Nullable String attributionTag) {
throw new RuntimeException("Not implemented. Must override in a subclass.");
}
+ // TODO moltmann: remove
+ /**
+ * @removed
+ */
+ @Deprecated
+ public @NonNull Context createFeatureContext(@Nullable String featureId) {
+ return createAttributionContext(featureId);
+ }
+
/**
* Return a new Context object for the current Context but whose storage
* APIs are backed by device-protected storage.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 91d214b..d389d2a 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -42,6 +42,7 @@
import android.os.UserHandle;
import android.view.Display;
import android.view.DisplayAdjustments;
+import android.view.WindowManager.LayoutParams.WindowType;
import android.view.autofill.AutofillManager.AutofillClient;
import java.io.File;
@@ -163,8 +164,8 @@
/** @hide */
@Override
- public @Nullable String getFeatureId() {
- return mBase.getFeatureId();
+ public @Nullable String getAttributionTag() {
+ return mBase.getAttributionTag();
}
@Override
@@ -978,13 +979,13 @@
@Override
@NonNull
- public Context createWindowContext(int type, @Nullable Bundle options) {
+ public Context createWindowContext(@WindowType int type, @Nullable Bundle options) {
return mBase.createWindowContext(type, options);
}
@Override
- public @NonNull Context createFeatureContext(@Nullable String featureId) {
- return mBase.createFeatureContext(featureId);
+ public @NonNull Context createAttributionContext(@Nullable String attributionTag) {
+ return mBase.createAttributionContext(attributionTag);
}
@Override
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 37643da..84b0f0e 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -38,7 +38,7 @@
* @hide
*/
public interface IContentProvider extends IInterface {
- public Cursor query(String callingPkg, @Nullable String featureId, Uri url,
+ public Cursor query(String callingPkg, @Nullable String attributionTag, Uri url,
@Nullable String[] projection,
@Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)
throws RemoteException;
@@ -59,8 +59,8 @@
throws RemoteException {
return insert(callingPkg, null, url, initialValues, null);
}
- public Uri insert(String callingPkg, String featureId, Uri url, ContentValues initialValues,
- Bundle extras) throws RemoteException;
+ public Uri insert(String callingPkg, String attributionTag, Uri url,
+ ContentValues initialValues, Bundle extras) throws RemoteException;
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
+ "ContentProviderClient#bulkInsert(android.net.Uri, android.content.ContentValues[])"
@@ -69,7 +69,7 @@
throws RemoteException {
return bulkInsert(callingPkg, null, url, initialValues);
}
- public int bulkInsert(String callingPkg, String featureId, Uri url,
+ public int bulkInsert(String callingPkg, String attributionTag, Uri url,
ContentValues[] initialValues) throws RemoteException;
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
@@ -80,7 +80,7 @@
return delete(callingPkg, null, url,
ContentResolver.createSqlQueryBundle(selection, selectionArgs));
}
- public int delete(String callingPkg, String featureId, Uri url, Bundle extras)
+ public int delete(String callingPkg, String attributionTag, Uri url, Bundle extras)
throws RemoteException;
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
@@ -91,18 +91,18 @@
return update(callingPkg, null, url, values,
ContentResolver.createSqlQueryBundle(selection, selectionArgs));
}
- public int update(String callingPkg, String featureId, Uri url, ContentValues values,
+ public int update(String callingPkg, String attributionTag, Uri url, ContentValues values,
Bundle extras) throws RemoteException;
- public ParcelFileDescriptor openFile(String callingPkg, @Nullable String featureId, Uri url,
- String mode, ICancellationSignal signal, IBinder callerToken)
+ public ParcelFileDescriptor openFile(String callingPkg, @Nullable String attributionTag,
+ Uri url, String mode, ICancellationSignal signal, IBinder callerToken)
throws RemoteException, FileNotFoundException;
- public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String featureId,
+ public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String attributionTag,
Uri url, String mode, ICancellationSignal signal)
throws RemoteException, FileNotFoundException;
- public ContentProviderResult[] applyBatch(String callingPkg, @Nullable String featureId,
+ public ContentProviderResult[] applyBatch(String callingPkg, @Nullable String attributionTag,
String authority, ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException;
@@ -115,15 +115,15 @@
return call(callingPkg, null, "unknown", method, arg, extras);
}
- public Bundle call(String callingPkg, @Nullable String featureId, String authority,
+ public Bundle call(String callingPkg, @Nullable String attributionTag, String authority,
String method, @Nullable String arg, @Nullable Bundle extras) throws RemoteException;
- public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri, int uid,
- int modeFlags) throws RemoteException;
+ public int checkUriPermission(String callingPkg, @Nullable String attributionTag, Uri uri,
+ int uid, int modeFlags) throws RemoteException;
public ICancellationSignal createCancellationSignal() throws RemoteException;
- public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri)
+ public Uri canonicalize(String callingPkg, @Nullable String attributionTag, Uri uri)
throws RemoteException;
/**
@@ -131,20 +131,21 @@
* call returns immediately, and the resulting type is returned when available via
* a binder callback.
*/
- void canonicalizeAsync(String callingPkg, @Nullable String featureId, Uri uri,
+ void canonicalizeAsync(String callingPkg, @Nullable String attributionTag, Uri uri,
RemoteCallback callback) throws RemoteException;
- public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri)
+ public Uri uncanonicalize(String callingPkg, @Nullable String attributionTag, Uri uri)
throws RemoteException;
- public boolean refresh(String callingPkg, @Nullable String featureId, Uri url,
+ public boolean refresh(String callingPkg, @Nullable String attributionTag, Uri url,
@Nullable Bundle extras, ICancellationSignal cancellationSignal) throws RemoteException;
// Data interchange.
public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException;
- public AssetFileDescriptor openTypedAssetFile(String callingPkg, @Nullable String featureId,
- Uri url, String mimeType, Bundle opts, ICancellationSignal signal)
+ public AssetFileDescriptor openTypedAssetFile(String callingPkg,
+ @Nullable String attributionTag, Uri url, String mimeType, Bundle opts,
+ ICancellationSignal signal)
throws RemoteException, FileNotFoundException;
/* IPC constants */
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 4bb7346..38c1890 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -26,6 +26,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.AppGlobals;
@@ -86,6 +87,7 @@
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
+import java.util.TimeZone;
/**
* An intent is an abstract description of an operation to be performed. It
@@ -2312,7 +2314,8 @@
/**
* Broadcast Action: The timezone has changed. The intent will have the following extra values:</p>
* <ul>
- * <li><em>time-zone</em> - The java.util.TimeZone.getID() value identifying the new time zone.</li>
+ * <li>{@link #EXTRA_TIMEZONE} - The java.util.TimeZone.getID() value identifying the new
+ * time zone.</li>
* </ul>
*
* <p class="note">This is a protected intent that can only be sent
@@ -5785,6 +5788,14 @@
public static final String EXTRA_TIME = "android.intent.extra.TIME";
/**
+ * Extra sent with {@link #ACTION_TIMEZONE_CHANGED} specifying the new time zone of the device.
+ *
+ * <p>Type: String, the same as returned by {@link TimeZone#getID()} to identify time zones.
+ */
+ @SuppressLint("ActionValue")
+ public static final String EXTRA_TIMEZONE = "time-zone";
+
+ /**
* Optional int extra for {@link #ACTION_TIME_CHANGED} that indicates the
* user has set their time format preference. See {@link #EXTRA_TIME_PREF_VALUE_USE_12_HOUR},
* {@link #EXTRA_TIME_PREF_VALUE_USE_24_HOUR} and
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index 33bd839..052c920 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -123,7 +123,7 @@
* @param uid The uid for which to check.
* @param packageName The package name for which to check. If null the
* the first package for the calling UID will be used.
- * @param featureId Feature in the package
+ * @param attributionTag attribution tag
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
* @param message A message describing the reason the permission was checked
@@ -133,9 +133,9 @@
@PermissionResult
public static int checkPermissionForDataDelivery(@NonNull Context context,
@NonNull String permission, int pid, int uid, @Nullable String packageName,
- @Nullable String featureId, @Nullable String message) {
- return checkPermissionCommon(context, permission, pid, uid, packageName, featureId, message,
- true /*forDataDelivery*/);
+ @Nullable String attributionTag, @Nullable String message) {
+ return checkPermissionCommon(context, permission, pid, uid, packageName, attributionTag,
+ message, true /*forDataDelivery*/);
}
/**
@@ -171,8 +171,8 @@
@PermissionResult
public static int checkPermissionForPreflight(@NonNull Context context,
@NonNull String permission, int pid, int uid, @Nullable String packageName) {
- return checkPermissionCommon(context, permission, pid, uid, packageName, null /*featureId*/,
- null /*message*/, false /*forDataDelivery*/);
+ return checkPermissionCommon(context, permission, pid, uid, packageName,
+ null /*attributionTag*/, null /*message*/, false /*forDataDelivery*/);
}
/**
@@ -207,7 +207,7 @@
public static int checkSelfPermissionForDataDelivery(@NonNull Context context,
@NonNull String permission, @Nullable String message) {
return checkPermissionForDataDelivery(context, permission, Process.myPid(),
- Process.myUid(), context.getPackageName(), context.getFeatureId(), message);
+ Process.myUid(), context.getPackageName(), context.getAttributionTag(), message);
}
/**
@@ -266,7 +266,7 @@
* @param permission The permission to check.
* @param packageName The package name making the IPC. If null the
* the first package for the calling UID will be used.
- * @param featureId The feature inside of the app
+ * @param attributionTag attribution tag
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
* @param message A message describing the reason the permission was checked
@@ -276,12 +276,12 @@
@PermissionResult
public static int checkCallingPermissionForDataDelivery(@NonNull Context context,
@NonNull String permission, @Nullable String packageName,
- @Nullable String featureId, @Nullable String message) {
+ @Nullable String attributionTag, @Nullable String message) {
if (Binder.getCallingPid() == Process.myPid()) {
return PERMISSION_HARD_DENIED;
}
return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
- Binder.getCallingUid(), packageName, featureId, message);
+ Binder.getCallingUid(), packageName, attributionTag, message);
}
/**
@@ -343,20 +343,20 @@
* @param permission The permission to check.
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
- * @param featureId feature Id of caller (if not self)
+ * @param attributionTag attribution tag of caller (if not self)
* @param message A message describing the reason the permission was checked
*
* @see #checkCallingOrSelfPermissionForPreflight(Context, String)
*/
@PermissionResult
public static int checkCallingOrSelfPermissionForDataDelivery(@NonNull Context context,
- @NonNull String permission, @Nullable String featureId, @Nullable String message) {
+ @NonNull String permission, @Nullable String attributionTag, @Nullable String message) {
String packageName = (Binder.getCallingPid() == Process.myPid())
? context.getPackageName() : null;
- featureId = (Binder.getCallingPid() == Process.myPid())
- ? context.getFeatureId() : featureId;
+ attributionTag = (Binder.getCallingPid() == Process.myPid())
+ ? context.getAttributionTag() : attributionTag;
return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
- Binder.getCallingUid(), packageName, featureId, message);
+ Binder.getCallingUid(), packageName, attributionTag, message);
}
/**
@@ -395,7 +395,7 @@
}
static int checkPermissionCommon(@NonNull Context context, @NonNull String permission,
- int pid, int uid, @Nullable String packageName, @Nullable String featureId,
+ int pid, int uid, @Nullable String packageName, @Nullable String attributionTag,
@Nullable String message, boolean forDataDelivery) {
final PermissionInfo permissionInfo;
try {
@@ -414,18 +414,18 @@
}
if (permissionInfo.isAppOp()) {
- return checkAppOpPermission(context, permission, pid, uid, packageName, featureId,
+ return checkAppOpPermission(context, permission, pid, uid, packageName, attributionTag,
message, forDataDelivery);
}
if (permissionInfo.isRuntime()) {
- return checkRuntimePermission(context, permission, pid, uid, packageName, featureId,
- message, forDataDelivery);
+ return checkRuntimePermission(context, permission, pid, uid, packageName,
+ attributionTag, message, forDataDelivery);
}
return context.checkPermission(permission, pid, uid);
}
private static int checkAppOpPermission(@NonNull Context context, @NonNull String permission,
- int pid, int uid, @Nullable String packageName, @Nullable String featureId,
+ int pid, int uid, @Nullable String packageName, @Nullable String attributionTag,
@Nullable String message, boolean forDataDelivery) {
final String op = AppOpsManager.permissionToOp(permission);
if (op == null || packageName == null) {
@@ -434,7 +434,7 @@
final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
final int opMode = (forDataDelivery)
- ? appOpsManager.noteProxyOpNoThrow(op, packageName, uid, featureId, message)
+ ? appOpsManager.noteProxyOpNoThrow(op, packageName, uid, attributionTag, message)
: appOpsManager.unsafeCheckOpNoThrow(op, uid, packageName);
switch (opMode) {
@@ -453,7 +453,7 @@
}
private static int checkRuntimePermission(@NonNull Context context, @NonNull String permission,
- int pid, int uid, @Nullable String packageName, @Nullable String featureId,
+ int pid, int uid, @Nullable String packageName, @Nullable String attributionTag,
@Nullable String message, boolean forDataDelivery) {
if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) {
return PERMISSION_HARD_DENIED;
@@ -466,7 +466,7 @@
final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
final int opMode = (forDataDelivery)
- ? appOpsManager.noteProxyOpNoThrow(op, packageName, uid, featureId, message)
+ ? appOpsManager.noteProxyOpNoThrow(op, packageName, uid, attributionTag, message)
: appOpsManager.unsafeCheckOpNoThrow(op, uid, packageName);
if (opMode == AppOpsManager.MODE_ALLOWED) {
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index a15afe0..c82fffa 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -25,6 +25,7 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ProcessInfo;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;
@@ -38,6 +39,8 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Parcelling;
+import com.android.internal.util.Parcelling.BuiltIn.ForBoolean;
import com.android.server.SystemConfig;
import java.lang.annotation.Retention;
@@ -56,7 +59,8 @@
* <application> tag.
*/
public class ApplicationInfo extends PackageItemInfo implements Parcelable {
-
+ private static ForBoolean sForBoolean = Parcelling.Cache.getOrCreate(ForBoolean.class);
+
/**
* Default task affinity of all activities in this application. See
* {@link ActivityInfo#taskAffinity} for more information. This comes
@@ -1273,6 +1277,14 @@
public String zygotePreloadName;
/**
+ * Indicates if the application has requested GWP-ASan to be enabled, disabled, or left
+ * unspecified. Processes can override this setting.
+ * @hide
+ */
+ @Nullable
+ public Boolean enableGwpAsan;
+
+ /**
* Represents the default policy. The actual policy used will depend on other properties of
* the application, e.g. the target SDK version.
* @hide
@@ -1413,6 +1425,9 @@
pw.println(prefix + "usesNonSdkApi=" + usesNonSdkApi());
pw.println(prefix + "allowsPlaybackCapture="
+ (isAudioPlaybackCaptureAllowed() ? "true" : "false"));
+ if (enableGwpAsan != null) {
+ pw.println(prefix + "enableGwpAsan=" + enableGwpAsan);
+ }
}
super.dumpBack(pw, prefix);
}
@@ -1511,6 +1526,9 @@
if (category != CATEGORY_UNDEFINED) {
proto.write(ApplicationInfoProto.Detail.CATEGORY, category);
}
+ if (enableGwpAsan != null) {
+ proto.write(ApplicationInfoProto.Detail.ENABLE_GWP_ASAN, enableGwpAsan);
+ }
proto.end(detailToken);
}
proto.end(token);
@@ -1620,6 +1638,7 @@
mHiddenApiPolicy = orig.mHiddenApiPolicy;
hiddenUntilInstalled = orig.hiddenUntilInstalled;
zygotePreloadName = orig.zygotePreloadName;
+ enableGwpAsan = orig.enableGwpAsan;
}
public String toString() {
@@ -1703,6 +1722,7 @@
dest.writeInt(mHiddenApiPolicy);
dest.writeInt(hiddenUntilInstalled ? 1 : 0);
dest.writeString(zygotePreloadName);
+ sForBoolean.parcel(enableGwpAsan, dest, parcelableFlags);
}
public static final @android.annotation.NonNull Parcelable.Creator<ApplicationInfo> CREATOR
@@ -1783,6 +1803,7 @@
mHiddenApiPolicy = source.readInt();
hiddenUntilInstalled = source.readInt() != 0;
zygotePreloadName = source.readString();
+ enableGwpAsan = sForBoolean.unparcel(source);
}
/**
@@ -2161,6 +2182,7 @@
/** {@hide} */ public void setResourcePath(String resourcePath) { scanPublicSourceDir = resourcePath; }
/** {@hide} */ public void setBaseResourcePath(String baseResourcePath) { publicSourceDir = baseResourcePath; }
/** {@hide} */ public void setSplitResourcePaths(String[] splitResourcePaths) { splitPublicSourceDirs = splitResourcePaths; }
+ /** {@hide} */ public void setGwpAsanEnabled(@Nullable Boolean value) { enableGwpAsan = value; }
/** {@hide} */
@UnsupportedAppUsage
@@ -2172,4 +2194,6 @@
@UnsupportedAppUsage
public String getBaseResourcePath() { return publicSourceDir; }
/** {@hide} */ public String[] getSplitResourcePaths() { return splitPublicSourceDirs; }
+ @Nullable
+ public Boolean isGwpAsanEnabled() { return enableGwpAsan; }
}
diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java
index 3261cb1..dc3a029 100644
--- a/core/java/android/content/pm/CrossProfileApps.java
+++ b/core/java/android/content/pm/CrossProfileApps.java
@@ -27,6 +27,7 @@
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -95,7 +96,7 @@
mService.startActivityAsUser(
mContext.getIApplicationThread(),
mContext.getPackageName(),
- mContext.getFeatureId(),
+ mContext.getAttributionTag(),
component,
targetUser.getIdentifier(),
true);
@@ -128,14 +129,44 @@
@NonNull Intent intent,
@NonNull UserHandle targetUser,
@Nullable Activity callingActivity) {
+ startActivity(intent, targetUser, callingActivity, /* options= */ null);
+ }
+
+ /**
+ * Starts the specified activity of the caller package in the specified profile.
+ *
+ * <p>The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES},
+ * {@code android.Manifest.permission#INTERACT_ACROSS_USERS}, or {@code
+ * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission. Both the caller and
+ * target user profiles must be in the same profile group. The target user must be a valid user
+ * returned from {@link #getTargetUserProfiles()}.
+ *
+ * @param intent The intent to launch. A component in the caller package must be specified.
+ * @param targetUser The {@link UserHandle} of the profile; must be one of the users returned by
+ * {@link #getTargetUserProfiles()} if different to the calling user, otherwise a
+ * {@link SecurityException} will be thrown.
+ * @param callingActivity The activity to start the new activity from for the purposes of
+ * deciding which task the new activity should belong to. If {@code null}, the activity
+ * will always be started in a new task.
+ * @param options The activity options or {@code null}. See {@link android.app.ActivityOptions}.
+ */
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.INTERACT_ACROSS_PROFILES,
+ android.Manifest.permission.INTERACT_ACROSS_USERS})
+ public void startActivity(
+ @NonNull Intent intent,
+ @NonNull UserHandle targetUser,
+ @Nullable Activity callingActivity,
+ @Nullable Bundle options) {
try {
mService.startActivityAsUserByIntent(
mContext.getIApplicationThread(),
mContext.getPackageName(),
- mContext.getFeatureId(),
+ mContext.getAttributionTag(),
intent,
targetUser.getIdentifier(),
- callingActivity != null ? callingActivity.getActivityToken() : null);
+ callingActivity != null ? callingActivity.getActivityToken() : null,
+ options);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
@@ -159,7 +190,7 @@
public void startActivity(@NonNull ComponentName component, @NonNull UserHandle targetUser) {
try {
mService.startActivityAsUser(mContext.getIApplicationThread(),
- mContext.getPackageName(), mContext.getFeatureId(), component,
+ mContext.getPackageName(), mContext.getAttributionTag(), component,
targetUser.getIdentifier(), false);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
diff --git a/core/java/android/content/pm/ICrossProfileApps.aidl b/core/java/android/content/pm/ICrossProfileApps.aidl
index 5a6e008..4cecb30 100644
--- a/core/java/android/content/pm/ICrossProfileApps.aidl
+++ b/core/java/android/content/pm/ICrossProfileApps.aidl
@@ -31,7 +31,8 @@
in String callingFeatureId, in ComponentName component, int userId,
boolean launchMainActivity);
void startActivityAsUserByIntent(in IApplicationThread caller, in String callingPackage,
- in String callingFeatureId, in Intent intent, int userId, in IBinder callingActivity);
+ in String callingFeatureId, in Intent intent, int userId, in IBinder callingActivity,
+ in Bundle options);
List<UserHandle> getTargetUserProfiles(in String callingPackage);
boolean canInteractAcrossProfiles(in String callingPackage);
boolean canRequestInteractAcrossProfiles(in String callingPackage);
diff --git a/core/java/android/content/pm/InstallSourceInfo.java b/core/java/android/content/pm/InstallSourceInfo.java
index c0fdcc9..a45bf79 100644
--- a/core/java/android/content/pm/InstallSourceInfo.java
+++ b/core/java/android/content/pm/InstallSourceInfo.java
@@ -66,7 +66,18 @@
mInstallingPackageName = source.readString();
}
- /** The name of the package that requested the installation, or null if not available. */
+ /**
+ * The name of the package that requested the installation, or null if not available.
+ *
+ * This is normally the same as the installing package name. If the installing package name
+ * is changed, for example by calling
+ * {@link PackageManager#setInstallerPackageName(String, String)}, the initiating package name
+ * remains unchanged. It continues to identify the actual package that performed the install
+ * or update.
+ * <p>
+ * Null may be returned if the app was not installed by a package (e.g. a system app or an app
+ * installed via adb) or if the initiating package has itself been uninstalled.
+ */
@Nullable
public String getInitiatingPackageName() {
return mInitiatingPackageName;
@@ -100,9 +111,11 @@
/**
* The name of the package responsible for the installation (the installer of record), or null
* if not available.
- * Note that this may differ from the initiating package name and can be modified.
- *
- * @see PackageManager#setInstallerPackageName(String, String)
+ * Note that this may differ from the initiating package name and can be modified via
+ * {@link PackageManager#setInstallerPackageName(String, String)}.
+ * <p>
+ * Null may be returned if the app was not installed by a package (e.g. a system app or an app
+ * installed via adb) or if the installing package has itself been uninstalled.
*/
@Nullable
public String getInstallingPackageName() {
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 86242fd..4e4897f 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -721,7 +721,7 @@
}
try {
mService.startActivityAsUser(mContext.getIApplicationThread(),
- mContext.getPackageName(), mContext.getFeatureId(),
+ mContext.getPackageName(), mContext.getAttributionTag(),
component, sourceBounds, opts, user);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
@@ -739,8 +739,8 @@
@Nullable Rect sourceBounds, @Nullable Bundle opts) {
try {
mService.startSessionDetailsActivityAsUser(mContext.getIApplicationThread(),
- mContext.getPackageName(), mContext.getFeatureId(), sessionInfo, sourceBounds,
- opts, sessionInfo.getUser());
+ mContext.getPackageName(), mContext.getAttributionTag(), sessionInfo,
+ sourceBounds, opts, sessionInfo.getUser());
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -760,7 +760,7 @@
logErrorForInvalidProfileAccess(user);
try {
mService.showAppDetailsAsUser(mContext.getIApplicationThread(),
- mContext.getPackageName(), mContext.getFeatureId(),
+ mContext.getPackageName(), mContext.getAttributionTag(),
component, sourceBounds, opts, user);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 1f53176..ec3590f 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -2323,6 +2323,7 @@
/**
* Get the value set in {@link SessionParams#setOriginatingUri(Uri)}.
+ * Note: This value will only be non-null for the owner of the session.
*/
public @Nullable Uri getOriginatingUri() {
return originatingUri;
@@ -2337,6 +2338,7 @@
/**
* Get the value set in {@link SessionParams#setReferrerUri(Uri)}
+ * Note: This value will only be non-null for the owner of the session.
*/
public @Nullable Uri getReferrerUri() {
return referrerUri;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index c6875a4..edf3134 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -190,7 +190,7 @@
public static final String TAG_OVERLAY = "overlay";
public static final String TAG_PACKAGE = "package";
public static final String TAG_PACKAGE_VERIFIER = "package-verifier";
- public static final String TAG_FEATURE = "feature";
+ public static final String TAG_ATTRIBUTION = "attribution";
public static final String TAG_PERMISSION = "permission";
public static final String TAG_PERMISSION_GROUP = "permission-group";
public static final String TAG_PERMISSION_TREE = "permission-tree";
diff --git a/core/java/android/content/pm/ProcessInfo.java b/core/java/android/content/pm/ProcessInfo.java
index c77a267..a373067 100644
--- a/core/java/android/content/pm/ProcessInfo.java
+++ b/core/java/android/content/pm/ProcessInfo.java
@@ -23,66 +23,157 @@
import android.text.TextUtils;
import android.util.ArraySet;
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+
/**
* Information about a process an app may run. This corresponds to information collected from the
* AndroidManifest.xml's <permission-group> tags.
* @hide
*/
+@DataClass(genGetters = true, genSetters = false, genParcelable = true, genAidl = false,
+ genBuilder = false)
public class ProcessInfo implements Parcelable {
/**
* The name of the process, fully-qualified based on the app's package name.
*/
+ @NonNull
public String name;
/**
* If non-null, these are permissions that are not allowed in this process.
*/
@Nullable
+ @DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedStringArraySet.class)
public ArraySet<String> deniedPermissions;
- public ProcessInfo(String name, ArraySet<String> deniedPermissions) {
- this.name = name;
- this.deniedPermissions = deniedPermissions;
- }
+ /**
+ * Indicates if the process has requested GWP-ASan to be enabled, disabled, or left unspecified.
+ */
+ @Nullable
+ public Boolean enableGwpAsan;
@Deprecated
public ProcessInfo(@NonNull ProcessInfo orig) {
this.name = orig.name;
this.deniedPermissions = orig.deniedPermissions;
+ this.enableGwpAsan = orig.enableGwpAsan;
}
- public int describeContents() {
- return 0;
+
+
+ // 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/content/pm/ProcessInfo.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new ProcessInfo.
+ *
+ * @param name
+ * The name of the process, fully-qualified based on the app's package name.
+ * @param deniedPermissions
+ * If non-null, these are permissions that are not allowed in this process.
+ * @param enableGwpAsan
+ * Indicates if the process has requested GWP-ASan to be enabled, disabled, or left unspecified.
+ */
+ @DataClass.Generated.Member
+ public ProcessInfo(
+ @NonNull String name,
+ @Nullable ArraySet<String> deniedPermissions,
+ @Nullable Boolean enableGwpAsan) {
+ this.name = name;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, name);
+ this.deniedPermissions = deniedPermissions;
+ this.enableGwpAsan = enableGwpAsan;
+
+ // onConstructed(); // You can define this method to get a callback
}
- public void writeToParcel(Parcel dest, int parcelableFlags) {
- dest.writeString(this.name);
- final int numDenied = this.deniedPermissions != null
- ? this.deniedPermissions.size() : 0;
- dest.writeInt(numDenied);
- for (int i = 0; i < numDenied; i++) {
- dest.writeString(this.deniedPermissions.valueAt(i));
+ @DataClass.Generated.Member
+ static Parcelling<ArraySet<String>> sParcellingForDeniedPermissions =
+ Parcelling.Cache.get(
+ Parcelling.BuiltIn.ForInternedStringArraySet.class);
+ static {
+ if (sParcellingForDeniedPermissions == null) {
+ sParcellingForDeniedPermissions = Parcelling.Cache.put(
+ new Parcelling.BuiltIn.ForInternedStringArraySet());
}
}
- public static final @NonNull Creator<ProcessInfo> CREATOR =
- new Creator<ProcessInfo>() {
- public ProcessInfo createFromParcel(Parcel source) {
- return new ProcessInfo(source);
- }
- public ProcessInfo[] newArray(int size) {
- return new ProcessInfo[size];
- }
- };
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
- private ProcessInfo(Parcel source) {
- this.name = source.readString();
- final int numDenied = source.readInt();
- if (numDenied > 0) {
- this.deniedPermissions = new ArraySet<>(numDenied);
- for (int i = numDenied - 1; i >= 0; i--) {
- this.deniedPermissions.add(TextUtils.safeIntern(source.readString()));
- }
- }
+ byte flg = 0;
+ if (deniedPermissions != null) flg |= 0x2;
+ if (enableGwpAsan != null) flg |= 0x4;
+ dest.writeByte(flg);
+ dest.writeString(name);
+ sParcellingForDeniedPermissions.parcel(deniedPermissions, dest, flags);
+ if (enableGwpAsan != null) dest.writeBoolean(enableGwpAsan);
}
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected ProcessInfo(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ String _name = in.readString();
+ ArraySet<String> _deniedPermissions = sParcellingForDeniedPermissions.unparcel(in);
+ Boolean _enableGwpAsan = (flg & 0x4) == 0 ? null : (Boolean) in.readBoolean();
+
+ this.name = _name;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, name);
+ this.deniedPermissions = _deniedPermissions;
+ this.enableGwpAsan = _enableGwpAsan;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<ProcessInfo> CREATOR
+ = new Parcelable.Creator<ProcessInfo>() {
+ @Override
+ public ProcessInfo[] newArray(int size) {
+ return new ProcessInfo[size];
+ }
+
+ @Override
+ public ProcessInfo createFromParcel(@NonNull Parcel in) {
+ return new ProcessInfo(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1582840056156L,
+ codegenVersion = "1.0.15",
+ sourceFile = "frameworks/base/core/java/android/content/pm/ProcessInfo.java",
+ inputSignatures = "public @android.annotation.NonNull java.lang.String name\npublic @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedStringArraySet.class) android.util.ArraySet<java.lang.String> deniedPermissions\npublic @android.annotation.Nullable java.lang.Boolean enableGwpAsan\nclass ProcessInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=false, genParcelable=true, genAidl=false, genBuilder=false)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
}
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 49e8c05..af87578 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -1558,11 +1558,6 @@
* "Rank" of a shortcut, which is a non-negative, sequential value that's unique for each
* {@link #getActivity} for each of the two types of shortcuts (static and dynamic).
*
- * <p>Because static shortcuts and dynamic shortcuts have overlapping ranks,
- * when a launcher app shows shortcuts for an activity, it should first show
- * the static shortcuts, followed by the dynamic shortcuts. Within each of those categories,
- * shortcuts should be sorted by rank in ascending order.
- *
* <p><em>Floating shortcuts</em>, or shortcuts that are neither static nor dynamic, will all
* have rank 0, because they aren't sorted.
*
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index aa93d80..1e02a7d 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -24,7 +24,7 @@
import android.content.pm.FeatureInfo;
import android.content.pm.PackageParser;
import android.content.pm.parsing.component.ParsedActivity;
-import android.content.pm.parsing.component.ParsedFeature;
+import android.content.pm.parsing.component.ParsedAttribution;
import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedIntentInfo;
import android.content.pm.parsing.component.ParsedPermission;
@@ -77,7 +77,7 @@
ParsingPackage addProvider(ParsedProvider parsedProvider);
- ParsingPackage addFeature(ParsedFeature permission);
+ ParsingPackage addAttribution(ParsedAttribution attribution);
ParsingPackage addReceiver(ParsedActivity parsedReceiver);
@@ -236,6 +236,8 @@
ParsingPackage setEnabled(boolean enabled);
+ ParsingPackage setGwpAsanEnabled(Boolean enableGwpAsan);
+
ParsingPackage setCrossProfile(boolean crossProfile);
ParsingPackage setFullBackupContent(int fullBackupContent);
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index a9b72d0..d7c0dfb 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -30,9 +30,10 @@
import android.content.pm.FeatureInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageParser;
+import android.content.pm.ProcessInfo;
import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedAttribution;
import android.content.pm.parsing.component.ParsedComponent;
-import android.content.pm.parsing.component.ParsedFeature;
import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedIntentInfo;
import android.content.pm.parsing.component.ParsedMainComponent;
@@ -243,7 +244,7 @@
protected List<ParsedProvider> providers = emptyList();
@NonNull
- private List<ParsedFeature> features = emptyList();
+ private List<ParsedAttribution> attributions = emptyList();
@NonNull
protected List<ParsedPermission> permissions = emptyList();
@@ -406,6 +407,10 @@
private boolean allowNativeHeapPointerTagging;
private boolean preserveLegacyExternalStorage;
+ @Nullable
+ @DataClass.ParcelWith(ForBoolean.class)
+ protected Boolean enableGwpAsan = null;
+
// TODO(chiuwinson): Non-null
@Nullable
private ArraySet<String> mimeGroups;
@@ -620,8 +625,8 @@
}
@Override
- public ParsingPackageImpl addFeature(ParsedFeature feature) {
- this.features = CollectionUtils.add(this.features, feature);
+ public ParsingPackageImpl addAttribution(ParsedAttribution attribution) {
+ this.attributions = CollectionUtils.add(this.attributions, attribution);
return this;
}
@@ -904,7 +909,7 @@
appInfo.volumeUuid = volumeUuid;
appInfo.zygotePreloadName = zygotePreloadName;
appInfo.crossProfile = isCrossProfile();
-
+ appInfo.setGwpAsanEnabled(enableGwpAsan);
appInfo.setBaseCodePath(baseCodePath);
appInfo.setBaseResourcePath(baseCodePath);
appInfo.setCodePath(codePath);
@@ -990,7 +995,7 @@
dest.writeTypedList(this.receivers);
dest.writeTypedList(this.services);
dest.writeTypedList(this.providers);
- dest.writeTypedList(this.features);
+ dest.writeTypedList(this.attributions);
dest.writeTypedList(this.permissions);
dest.writeTypedList(this.permissionGroups);
dest.writeTypedList(this.instrumentations);
@@ -1086,6 +1091,7 @@
dest.writeBoolean(this.allowNativeHeapPointerTagging);
dest.writeBoolean(this.preserveLegacyExternalStorage);
dest.writeArraySet(this.mimeGroups);
+ sForBoolean.parcel(this.enableGwpAsan, dest, flags);
}
public ParsingPackageImpl(Parcel in) {
@@ -1149,7 +1155,7 @@
this.receivers = in.createTypedArrayList(ParsedActivity.CREATOR);
this.services = in.createTypedArrayList(ParsedService.CREATOR);
this.providers = in.createTypedArrayList(ParsedProvider.CREATOR);
- this.features = in.createTypedArrayList(ParsedFeature.CREATOR);
+ this.attributions = in.createTypedArrayList(ParsedAttribution.CREATOR);
this.permissions = in.createTypedArrayList(ParsedPermission.CREATOR);
this.permissionGroups = in.createTypedArrayList(ParsedPermissionGroup.CREATOR);
this.instrumentations = in.createTypedArrayList(ParsedInstrumentation.CREATOR);
@@ -1243,6 +1249,7 @@
this.allowNativeHeapPointerTagging = in.readBoolean();
this.preserveLegacyExternalStorage = in.readBoolean();
this.mimeGroups = (ArraySet<String>) in.readArraySet(boot);
+ this.enableGwpAsan = sForBoolean.unparcel(in);
}
public static final Parcelable.Creator<ParsingPackageImpl> CREATOR =
@@ -1509,8 +1516,8 @@
@NonNull
@Override
- public List<ParsedFeature> getFeatures() {
- return features;
+ public List<ParsedAttribution> getAttributions() {
+ return attributions;
}
@NonNull
@@ -1965,6 +1972,12 @@
}
@Override
+ @Nullable
+ public Boolean isGwpAsanEnabled() {
+ return enableGwpAsan;
+ }
+
+ @Override
public boolean isPartiallyDirectBootAware() {
return partiallyDirectBootAware;
}
@@ -2420,6 +2433,12 @@
}
@Override
+ public ParsingPackageImpl setGwpAsanEnabled(@Nullable Boolean value) {
+ enableGwpAsan = value;
+ return this;
+ }
+
+ @Override
public ParsingPackageImpl setPartiallyDirectBootAware(boolean value) {
partiallyDirectBootAware = value;
return this;
diff --git a/core/java/android/content/pm/parsing/ParsingPackageRead.java b/core/java/android/content/pm/parsing/ParsingPackageRead.java
index 048b924..0b673b5 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageRead.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageRead.java
@@ -28,7 +28,7 @@
import android.content.pm.PackageParser;
import android.content.pm.ServiceInfo;
import android.content.pm.parsing.component.ParsedActivity;
-import android.content.pm.parsing.component.ParsedFeature;
+import android.content.pm.parsing.component.ParsedAttribution;
import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedIntentInfo;
import android.content.pm.parsing.component.ParsedPermission;
@@ -80,7 +80,7 @@
List<ConfigurationInfo> getConfigPreferences();
@NonNull
- List<ParsedFeature> getFeatures();
+ List<ParsedAttribution> getAttributions();
/**
* @see PackageInfo#featureGroups
@@ -840,6 +840,13 @@
@Nullable
Set<String> getMimeGroups();
+ /**
+ * @see ApplicationInfo#enableGwpAsan
+ * @see R.styleable#AndroidManifest_enableGwpAsan
+ */
+ @Nullable
+ public Boolean isGwpAsanEnabled();
+
// TODO(b/135203078): Hide and enforce going through PackageInfoUtils
ApplicationInfo toAppInfoWithoutState();
}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index b4f2159..3ed0fd5 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -40,6 +40,7 @@
import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageParserException;
@@ -48,8 +49,8 @@
import android.content.pm.parsing.component.ComponentParseUtils;
import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedActivityUtils;
-import android.content.pm.parsing.component.ParsedFeature;
-import android.content.pm.parsing.component.ParsedFeatureUtils;
+import android.content.pm.parsing.component.ParsedAttribution;
+import android.content.pm.parsing.component.ParsedAttributionUtils;
import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedInstrumentationUtils;
import android.content.pm.parsing.component.ParsedIntentInfo;
@@ -672,7 +673,7 @@
);
}
- if (!ParsedFeature.isCombinationValid(pkg.getFeatures())) {
+ if (!ParsedAttribution.isCombinationValid(pkg.getAttributions())) {
return input.error(
INSTALL_PARSE_FAILED_BAD_MANIFEST,
"Combination <feature> tags are not valid"
@@ -707,8 +708,9 @@
return parseOverlay(input, pkg, res, parser);
case PackageParser.TAG_KEY_SETS:
return parseKeySets(input, pkg, res, parser);
- case PackageParser.TAG_FEATURE:
- return parseFeature(input, pkg, res, parser);
+ case "feature": // TODO moltmann: Remove
+ case PackageParser.TAG_ATTRIBUTION:
+ return parseAttribution(input, pkg, res, parser);
case PackageParser.TAG_PERMISSION_GROUP:
return parsePermissionGroup(input, pkg, res, parser);
case PackageParser.TAG_PERMISSION:
@@ -917,13 +919,15 @@
return input.success(pkg);
}
- private static ParseResult<ParsingPackage> parseFeature(ParseInput input, ParsingPackage pkg,
- Resources res, XmlResourceParser parser) throws IOException, XmlPullParserException {
- ParseResult<ParsedFeature> result = ParsedFeatureUtils.parseFeature(res, parser, input);
+ private static ParseResult<ParsingPackage> parseAttribution(ParseInput input,
+ ParsingPackage pkg, Resources res, XmlResourceParser parser)
+ throws IOException, XmlPullParserException {
+ ParseResult<ParsedAttribution> result = ParsedAttributionUtils.parseAttribution(res,
+ parser, input);
if (result.isError()) {
return input.error(result);
}
- return input.success(pkg.addFeature(result.getResult()));
+ return input.success(pkg.addAttribution(result.getResult()));
}
private static ParseResult<ParsingPackage> parsePermissionGroup(ParseInput input,
@@ -1660,6 +1664,11 @@
&& !ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
return input.error("Invalid class loader name: " + classLoaderName);
}
+
+ if (sa.hasValue(R.styleable.AndroidManifestApplication_enableGwpAsan)) {
+ pkg.setGwpAsanEnabled(
+ sa.getBoolean(R.styleable.AndroidManifestApplication_enableGwpAsan, false));
+ }
} finally {
sa.recycle();
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedAttribution.java b/core/java/android/content/pm/parsing/component/ParsedAttribution.java
new file mode 100644
index 0000000..02b3c7d
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedAttribution.java
@@ -0,0 +1,229 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StringRes;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArraySet;
+
+import com.android.internal.util.DataClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A {@link android.R.styleable#AndroidManifestAttribution <attribution>} tag parsed from the
+ * manifest.
+ *
+ * @hide
+ */
+@DataClass(genAidl = false)
+public class ParsedAttribution implements Parcelable {
+ /** Maximum length of attribution tag */
+ public static final int MAX_ATTRIBUTION_TAG_LEN = 50;
+
+ /** Maximum amount of attributions per package */
+ private static final int MAX_NUM_ATTRIBUTIONS = 1000;
+
+ /** Tag of the attribution */
+ public final @NonNull String tag;
+
+ /** User visible label fo the attribution */
+ public final @StringRes int label;
+
+ /** Ids of previously declared attributions this attribution inherits from */
+ public final @NonNull List<String> inheritFrom;
+
+ /**
+ * @return Is this set of attributions a valid combination for a single package?
+ */
+ public static boolean isCombinationValid(@Nullable List<ParsedAttribution> attributions) {
+ if (attributions == null) {
+ return true;
+ }
+
+ ArraySet<String> attributionTags = new ArraySet<>(attributions.size());
+ ArraySet<String> inheritFromAttributionTags = new ArraySet<>();
+
+ int numAttributions = attributions.size();
+ if (numAttributions > MAX_NUM_ATTRIBUTIONS) {
+ return false;
+ }
+
+ for (int attributionNum = 0; attributionNum < numAttributions; attributionNum++) {
+ boolean wasAdded = attributionTags.add(attributions.get(attributionNum).tag);
+ if (!wasAdded) {
+ // feature id is not unique
+ return false;
+ }
+ }
+
+ for (int attributionNum = 0; attributionNum < numAttributions; attributionNum++) {
+ ParsedAttribution feature = attributions.get(attributionNum);
+
+ int numInheritFrom = feature.inheritFrom.size();
+ for (int inheritFromNum = 0; inheritFromNum < numInheritFrom; inheritFromNum++) {
+ String inheritFrom = feature.inheritFrom.get(inheritFromNum);
+
+ if (attributionTags.contains(inheritFrom)) {
+ // Cannot inherit from a attribution that is still defined
+ return false;
+ }
+
+ boolean wasAdded = inheritFromAttributionTags.add(inheritFrom);
+ if (!wasAdded) {
+ // inheritFrom is not unique
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+
+
+ // Code below generated by codegen v1.0.14.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedAttribution.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @android.annotation.IntDef(prefix = "MAX_", value = {
+ MAX_ATTRIBUTION_TAG_LEN,
+ MAX_NUM_ATTRIBUTIONS
+ })
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+ @DataClass.Generated.Member
+ public @interface Max {}
+
+ @DataClass.Generated.Member
+ public static String maxToString(@Max int value) {
+ switch (value) {
+ case MAX_ATTRIBUTION_TAG_LEN:
+ return "MAX_ATTRIBUTION_TAG_LEN";
+ case MAX_NUM_ATTRIBUTIONS:
+ return "MAX_NUM_ATTRIBUTIONS";
+ default: return Integer.toHexString(value);
+ }
+ }
+
+ /**
+ * Creates a new ParsedAttribution.
+ *
+ * @param tag
+ * Tag of the attribution
+ * @param label
+ * User visible label fo the attribution
+ * @param inheritFrom
+ * Ids of previously declared attributions this attribution inherits from
+ */
+ @DataClass.Generated.Member
+ public ParsedAttribution(
+ @NonNull String tag,
+ @StringRes int label,
+ @NonNull List<String> inheritFrom) {
+ this.tag = tag;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, tag);
+ this.label = label;
+ com.android.internal.util.AnnotationValidations.validate(
+ StringRes.class, null, label);
+ this.inheritFrom = inheritFrom;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, inheritFrom);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeString(tag);
+ dest.writeInt(label);
+ dest.writeStringList(inheritFrom);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected ParsedAttribution(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ String _tag = in.readString();
+ int _label = in.readInt();
+ List<String> _inheritFrom = new ArrayList<>();
+ in.readStringList(_inheritFrom);
+
+ this.tag = _tag;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, tag);
+ this.label = _label;
+ com.android.internal.util.AnnotationValidations.validate(
+ StringRes.class, null, label);
+ this.inheritFrom = _inheritFrom;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, inheritFrom);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<ParsedAttribution> CREATOR
+ = new Parcelable.Creator<ParsedAttribution>() {
+ @Override
+ public ParsedAttribution[] newArray(int size) {
+ return new ParsedAttribution[size];
+ }
+
+ @Override
+ public ParsedAttribution createFromParcel(@NonNull Parcel in) {
+ return new ParsedAttribution(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1583436566499L,
+ codegenVersion = "1.0.14",
+ sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedAttribution.java",
+ inputSignatures = "public static final int MAX_ATTRIBUTION_TAG_LEN\nprivate static final int MAX_NUM_ATTRIBUTIONS\npublic final @android.annotation.NonNull java.lang.String tag\npublic final @android.annotation.StringRes int label\npublic final @android.annotation.NonNull java.util.List<java.lang.String> inheritFrom\npublic static boolean isCombinationValid(java.util.List<android.content.pm.parsing.component.ParsedAttribution>)\nclass ParsedAttribution extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genAidl=false)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedFeatureUtils.java b/core/java/android/content/pm/parsing/component/ParsedAttributionUtils.java
similarity index 63%
rename from core/java/android/content/pm/parsing/component/ParsedFeatureUtils.java
rename to core/java/android/content/pm/parsing/component/ParsedAttributionUtils.java
index fb52801..c4b1a0e 100644
--- a/core/java/android/content/pm/parsing/component/ParsedFeatureUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedAttributionUtils.java
@@ -34,34 +34,40 @@
import java.util.List;
/** @hide */
-public class ParsedFeatureUtils {
+public class ParsedAttributionUtils {
@NonNull
- public static ParseResult<ParsedFeature> parseFeature(Resources res, XmlResourceParser parser,
- ParseInput input) throws IOException, XmlPullParserException {
- String featureId;
+ public static ParseResult<ParsedAttribution> parseAttribution(Resources res,
+ XmlResourceParser parser, ParseInput input)
+ throws IOException, XmlPullParserException {
+ String attributionTag;
int label;
List<String> inheritFrom = null;
- TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestFeature);
+ TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestAttribution);
if (sa == null) {
- return input.error("<feature> could not be parsed");
+ return input.error("<attribution> could not be parsed");
}
try {
- featureId = sa.getNonConfigurationString(R.styleable.AndroidManifestFeature_featureId,
- 0);
- if (featureId == null) {
- return input.error("<featureId> does not specify android:featureId");
+ attributionTag = sa.getNonConfigurationString(
+ R.styleable.AndroidManifestAttribution_tag, 0);
+ if (attributionTag == null) {
+ // TODO moltmann: Remove handling of featureId
+ attributionTag = sa.getNonConfigurationString(
+ R.styleable.AndroidManifestAttribution_featureId, 0);
+ if (attributionTag == null) {
+ return input.error("<attribution> does not specify android:tag");
+ }
}
- if (featureId.length() > ParsedFeature.MAX_FEATURE_ID_LEN) {
- return input.error("<featureId> is too long. Max length is "
- + ParsedFeature.MAX_FEATURE_ID_LEN);
+ if (attributionTag.length() > ParsedAttribution.MAX_ATTRIBUTION_TAG_LEN) {
+ return input.error("android:tag is too long. Max length is "
+ + ParsedAttribution.MAX_ATTRIBUTION_TAG_LEN);
}
- label = sa.getResourceId(R.styleable.AndroidManifestFeature_label, 0);
+ label = sa.getResourceId(R.styleable.AndroidManifestAttribution_label, 0);
if (label == Resources.ID_NULL) {
- return input.error("<featureId> does not specify android:label");
+ return input.error("<attribution> does not specify android:label");
}
} finally {
sa.recycle();
@@ -77,14 +83,15 @@
String tagName = parser.getName();
if (tagName.equals("inherit-from")) {
- sa = res.obtainAttributes(parser, R.styleable.AndroidManifestFeatureInheritFrom);
+ sa = res.obtainAttributes(parser,
+ R.styleable.AndroidManifestAttributionInheritFrom);
if (sa == null) {
return input.error("<inherit-from> could not be parsed");
}
try {
String inheritFromId = sa.getNonConfigurationString(
- R.styleable.AndroidManifestFeatureInheritFrom_featureId,0);
+ R.styleable.AndroidManifestAttributionInheritFrom_tag, 0);
if (inheritFrom == null) {
inheritFrom = new ArrayList<>();
@@ -94,7 +101,7 @@
sa.recycle();
}
} else {
- return input.error("Bad element under <feature>: " + tagName);
+ return input.error("Bad element under <attribution>: " + tagName);
}
}
@@ -104,6 +111,6 @@
((ArrayList) inheritFrom).trimToSize();
}
- return input.success(new ParsedFeature(featureId, label, inheritFrom));
+ return input.success(new ParsedAttribution(attributionTag, label, inheritFrom));
}
}
diff --git a/core/java/android/content/pm/parsing/component/ParsedFeature.java b/core/java/android/content/pm/parsing/component/ParsedFeature.java
deleted file mode 100644
index b8a9098..0000000
--- a/core/java/android/content/pm/parsing/component/ParsedFeature.java
+++ /dev/null
@@ -1,229 +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.content.pm.parsing.component;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.StringRes;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.ArraySet;
-
-import com.android.internal.util.DataClass;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A {@link android.R.styleable#AndroidManifestFeature <feature>} tag parsed from the
- * manifest.
- *
- * @hide
- */
-@DataClass(genAidl = false)
-public class ParsedFeature implements Parcelable {
- /** Maximum length of featureId */
- public static final int MAX_FEATURE_ID_LEN = 50;
-
- /** Maximum amount of features per package */
- private static final int MAX_NUM_FEATURES = 1000;
-
- /** Id of the feature */
- public final @NonNull String id;
-
- /** User visible label fo the feature */
- public final @StringRes int label;
-
- /** Ids of previously declared features this feature inherits from */
- public final @NonNull List<String> inheritFrom;
-
- /**
- * @return Is this set of features a valid combination for a single package?
- */
- public static boolean isCombinationValid(@Nullable List<ParsedFeature> features) {
- if (features == null) {
- return true;
- }
-
- ArraySet<String> featureIds = new ArraySet<>(features.size());
- ArraySet<String> inheritFromFeatureIds = new ArraySet<>();
-
- int numFeatures = features.size();
- if (numFeatures > MAX_NUM_FEATURES) {
- return false;
- }
-
- for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
- boolean wasAdded = featureIds.add(features.get(featureNum).id);
- if (!wasAdded) {
- // feature id is not unique
- return false;
- }
- }
-
- for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
- ParsedFeature feature = features.get(featureNum);
-
- int numInheritFrom = feature.inheritFrom.size();
- for (int inheritFromNum = 0; inheritFromNum < numInheritFrom; inheritFromNum++) {
- String inheritFrom = feature.inheritFrom.get(inheritFromNum);
-
- if (featureIds.contains(inheritFrom)) {
- // Cannot inherit from a feature that is still defined
- return false;
- }
-
- boolean wasAdded = inheritFromFeatureIds.add(inheritFrom);
- if (!wasAdded) {
- // inheritFrom is not unique
- return false;
- }
- }
- }
-
- return true;
- }
-
-
-
- // Code below generated by codegen v1.0.14.
- //
- // DO NOT MODIFY!
- // CHECKSTYLE:OFF Generated code
- //
- // To regenerate run:
- // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedFeature.java
- //
- // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
- // Settings > Editor > Code Style > Formatter Control
- //@formatter:off
-
-
- @android.annotation.IntDef(prefix = "MAX_", value = {
- MAX_FEATURE_ID_LEN,
- MAX_NUM_FEATURES
- })
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
- @DataClass.Generated.Member
- public @interface Max {}
-
- @DataClass.Generated.Member
- public static String maxToString(@Max int value) {
- switch (value) {
- case MAX_FEATURE_ID_LEN:
- return "MAX_FEATURE_ID_LEN";
- case MAX_NUM_FEATURES:
- return "MAX_NUM_FEATURES";
- default: return Integer.toHexString(value);
- }
- }
-
- /**
- * Creates a new ParsedFeature.
- *
- * @param id
- * Id of the feature
- * @param label
- * User visible label fo the feature
- * @param inheritFrom
- * Ids of previously declared features this feature inherits from
- */
- @DataClass.Generated.Member
- public ParsedFeature(
- @NonNull String id,
- @StringRes int label,
- @NonNull List<String> inheritFrom) {
- this.id = id;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, id);
- this.label = label;
- com.android.internal.util.AnnotationValidations.validate(
- StringRes.class, null, label);
- this.inheritFrom = inheritFrom;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, inheritFrom);
-
- // onConstructed(); // You can define this method to get a callback
- }
-
- @Override
- @DataClass.Generated.Member
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- // You can override field parcelling by defining methods like:
- // void parcelFieldName(Parcel dest, int flags) { ... }
-
- dest.writeString(id);
- dest.writeInt(label);
- dest.writeStringList(inheritFrom);
- }
-
- @Override
- @DataClass.Generated.Member
- public int describeContents() { return 0; }
-
- /** @hide */
- @SuppressWarnings({"unchecked", "RedundantCast"})
- @DataClass.Generated.Member
- protected ParsedFeature(@NonNull Parcel in) {
- // You can override field unparcelling by defining methods like:
- // static FieldType unparcelFieldName(Parcel in) { ... }
-
- String _id = in.readString();
- int _label = in.readInt();
- List<String> _inheritFrom = new ArrayList<>();
- in.readStringList(_inheritFrom);
-
- this.id = _id;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, id);
- this.label = _label;
- com.android.internal.util.AnnotationValidations.validate(
- StringRes.class, null, label);
- this.inheritFrom = _inheritFrom;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, inheritFrom);
-
- // onConstructed(); // You can define this method to get a callback
- }
-
- @DataClass.Generated.Member
- public static final @NonNull Parcelable.Creator<ParsedFeature> CREATOR
- = new Parcelable.Creator<ParsedFeature>() {
- @Override
- public ParsedFeature[] newArray(int size) {
- return new ParsedFeature[size];
- }
-
- @Override
- public ParsedFeature createFromParcel(@NonNull Parcel in) {
- return new ParsedFeature(in);
- }
- };
-
- @DataClass.Generated(
- time = 1581379861853L,
- codegenVersion = "1.0.14",
- sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedFeature.java",
- inputSignatures = "public static final int MAX_FEATURE_ID_LEN\nprivate static final int MAX_NUM_FEATURES\npublic final @android.annotation.NonNull java.lang.String id\npublic final @android.annotation.StringRes int label\npublic final @android.annotation.NonNull java.util.List<java.lang.String> inheritFrom\npublic static boolean isCombinationValid(java.util.List<android.content.pm.parsing.component.ParsedFeature>)\nclass ParsedFeature extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genAidl=false)")
- @Deprecated
- private void __metadata() {}
-
-
- //@formatter:on
- // End of generated code
-
-}
diff --git a/core/java/android/content/pm/parsing/component/ParsedProcess.java b/core/java/android/content/pm/parsing/component/ParsedProcess.java
index da7bf98..3b6020a 100644
--- a/core/java/android/content/pm/parsing/component/ParsedProcess.java
+++ b/core/java/android/content/pm/parsing/component/ParsedProcess.java
@@ -41,6 +41,9 @@
@DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedStringSet.class)
protected Set<String> deniedPermissions = emptySet();
+ @Nullable
+ protected Boolean enableGwpAsan = null;
+
public ParsedProcess() {
}
@@ -71,13 +74,15 @@
@DataClass.Generated.Member
public ParsedProcess(
@NonNull String name,
- @NonNull Set<String> deniedPermissions) {
+ @NonNull Set<String> deniedPermissions,
+ @Nullable Boolean enableGwpAsan) {
this.name = name;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, name);
this.deniedPermissions = deniedPermissions;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, deniedPermissions);
+ this.enableGwpAsan = enableGwpAsan;
// onConstructed(); // You can define this method to get a callback
}
@@ -93,6 +98,11 @@
}
@DataClass.Generated.Member
+ public @Nullable Boolean getEnableGwpAsan() {
+ return enableGwpAsan;
+ }
+
+ @DataClass.Generated.Member
static Parcelling<Set<String>> sParcellingForDeniedPermissions =
Parcelling.Cache.get(
Parcelling.BuiltIn.ForInternedStringSet.class);
@@ -109,8 +119,12 @@
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
+ byte flg = 0;
+ if (enableGwpAsan != null) flg |= 0x4;
+ dest.writeByte(flg);
dest.writeString(name);
sParcellingForDeniedPermissions.parcel(deniedPermissions, dest, flags);
+ if (enableGwpAsan != null) dest.writeBoolean(enableGwpAsan);
}
@Override
@@ -124,8 +138,10 @@
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
+ byte flg = in.readByte();
String _name = in.readString();
Set<String> _deniedPermissions = sParcellingForDeniedPermissions.unparcel(in);
+ Boolean _enableGwpAsan = (flg & 0x4) == 0 ? null : (Boolean) in.readBoolean();
this.name = _name;
com.android.internal.util.AnnotationValidations.validate(
@@ -133,6 +149,7 @@
this.deniedPermissions = _deniedPermissions;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, deniedPermissions);
+ this.enableGwpAsan = _enableGwpAsan;
// onConstructed(); // You can define this method to get a callback
}
@@ -152,10 +169,10 @@
};
@DataClass.Generated(
- time = 1581452315946L,
+ time = 1582589960479L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedProcess.java",
- inputSignatures = "protected @android.annotation.NonNull java.lang.String name\nprotected @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedStringSet.class) java.util.Set<java.lang.String> deniedPermissions\npublic void addStateFrom(android.content.pm.parsing.component.ParsedProcess)\nclass ParsedProcess extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=false, genParcelable=true, genAidl=false, genBuilder=false)")
+ inputSignatures = "protected @android.annotation.NonNull java.lang.String name\nprotected @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedStringSet.class) java.util.Set<java.lang.String> deniedPermissions\nprotected @android.annotation.Nullable java.lang.Boolean enableGwpAsan\npublic void addStateFrom(android.content.pm.parsing.component.ParsedProcess)\nclass ParsedProcess extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=false, genParcelable=true, genAidl=false, genBuilder=false)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java b/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java
index 4825066..3820790 100644
--- a/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java
@@ -103,6 +103,11 @@
if (proc.name == null || proc.name.length() <= 0) {
return input.error("<process> does not specify android:process");
}
+
+ if (sa.hasValue(R.styleable.AndroidManifestProcess_enableGwpAsan)) {
+ proc.enableGwpAsan =
+ sa.getBoolean(R.styleable.AndroidManifestProcess_enableGwpAsan, false);
+ }
} finally {
sa.recycle();
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index a091f84..972b0f55 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -486,7 +486,7 @@
"Camera service is currently unavailable");
}
cameraUser = cameraService.connectDevice(callbacks, cameraId,
- mContext.getOpPackageName(), mContext.getFeatureId(), uid);
+ mContext.getOpPackageName(), mContext.getAttributionTag(), uid);
} else {
// Use legacy camera implementation for HAL1 devices
int id;
diff --git a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
index bf641d7..1aeb76a3 100644
--- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
+++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
@@ -28,7 +28,6 @@
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.Slog;
import android.util.Xml;
@@ -231,15 +230,7 @@
com.android.internal.R.styleable.VoiceEnrollmentApplication);
keyphraseMetadata = getKeyphraseFromTypedArray(array, packageName, parseErrors);
array.recycle();
- } catch (XmlPullParserException e) {
- String error = "Error parsing keyphrase enrollment meta-data for " + packageName;
- parseErrors.add(error + ": " + e);
- Slog.w(TAG, error, e);
- } catch (IOException e) {
- String error = "Error parsing keyphrase enrollment meta-data for " + packageName;
- parseErrors.add(error + ": " + e);
- Slog.w(TAG, error, e);
- } catch (PackageManager.NameNotFoundException e) {
+ } catch (XmlPullParserException | PackageManager.NameNotFoundException | IOException e) {
String error = "Error parsing keyphrase enrollment meta-data for " + packageName;
parseErrors.add(error + ": " + e);
Slog.w(TAG, error, e);
@@ -390,7 +381,6 @@
* False if not.
*/
public boolean isUidSupportedEnrollmentApplication(int uid) {
- Log.d(TAG, "isUidSupportedEnrollmentApplication: " + toString());
return mEnrollmentApplicationUids.contains(uid);
}
diff --git a/core/java/android/os/ConfigUpdate.java b/core/java/android/os/ConfigUpdate.java
index 9c999b2..590fbb3 100644
--- a/core/java/android/os/ConfigUpdate.java
+++ b/core/java/android/os/ConfigUpdate.java
@@ -16,6 +16,7 @@
package android.os;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
/**
@@ -114,20 +115,36 @@
= "android.os.action.UPDATE_CARRIER_ID_DB";
/**
- * Broadcast intent action indicating that the updated emergency number database is available.
- * <p>Extra: "VERSION" the numeric version of the new data. Devices should only install if the
- * update version is newer than the current one.
- * <p>Extra: "REQUIRED_HASH" the hash of the current update data.
- * <p>Input: {@link android.content.Intent#getData} is URI of downloaded emergency number file.
- * Devices should pick up the downloaded file and persist to the database
- * {@code com.android.internal.telephony.emergency.EmergencyNumberTracker}.
+ * Update the emergency number database into the devices.
+ * <p>Extra: {@link #EXTRA_VERSION} the numeric version of the database.
+ * <p>Extra: {@link #EXTRA_REQUIRED_HASH} the hash of the database.
+ * <p>Input: {@link android.content.Intent#getData} the URI to download emergency number
+ * database.
*
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.UPDATE_CONFIG)
public static final String ACTION_UPDATE_EMERGENCY_NUMBER_DB =
"android.os.action.UPDATE_EMERGENCY_NUMBER_DB";
+ /**
+ * An integer to indicate the numeric version of the new data. Devices should only install
+ * if the update version is newer than the current one.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_VERSION = "android.os.extra.VERSION";
+
+ /**
+ * A string to indicate the hash of the data.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_REQUIRED_HASH = "android.os.extra.REQUIRED_HASH";
+
private ConfigUpdate() {
}
}
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index b478dbe..a7e3263 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -77,6 +77,7 @@
@UnsupportedAppUsage
final MessageQueue mQueue;
final Thread mThread;
+ private boolean mInLoop;
@UnsupportedAppUsage
private Printer mLogging;
@@ -155,6 +156,12 @@
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
+ if (me.mInLoop) {
+ Slog.w(TAG, "Loop again would have the queued messages be executed"
+ + " before this one completed.");
+ }
+
+ me.mInLoop = true;
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
diff --git a/core/java/android/os/Users.md b/core/java/android/os/Users.md
new file mode 100644
index 0000000..3bbbe54
--- /dev/null
+++ b/core/java/android/os/Users.md
@@ -0,0 +1,109 @@
+<!--
+ 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
+ -->
+
+# Users for system developers
+
+## Concepts
+
+### User
+
+A user of a device e.g. usually a human being. Each user has its own home screen.
+
+#### User Profile
+
+A user can have multiple profiles. E.g. one for the private life and one for work. Each profile
+has a different set of apps and accounts but they share one home screen. All profiles of a
+profile group can be active at the same time.
+
+Each profile has a separate [`userId`](#int-userid). Unless needed user profiles are treated as
+completely separate users.
+
+#### Profile Group
+
+All user profiles that share a home screen. You can list the profiles of a user via
+`UserManager#getEnabledProfiles` (you usually don't deal with disabled profiles)
+
+#### Foreground user vs background user
+
+Only a single user profile group can be in the foreground. This is the user profile the user
+currently interacts with.
+
+#### Parent user (profile)
+
+The main profile of a profile group, usually the personal (as opposed to work) profile. Get this via
+`UserManager#getProfileParent` (returns `null` if the user does not have profiles)
+
+#### Managed user (profile)
+
+The other profiles of a profile group. The name comes from the fact that these profiles are usually
+managed by a device policy controller app. You can create a managed profile from within the device
+policy controller app on your phone.
+
+#### Account
+
+An account of a user profile with a (usually internet based) service. E.g. aname@gmail.com or
+aname@yahoo.com. Each profile can have multiple accounts. A profile does not have to have a
+account.
+
+## Data types
+
+### int userId
+
+... usually marked as `@UserIdInt`
+
+The id of a user profile. List all users via `adb shell dumpsys user`. There is no data type for a
+user, all you can do is using the user id of the parent profile as a proxy for the user.
+
+### int uid
+
+Identity of an app. This is the same as a Linux uid, but in Android there is one uid per package,
+per user.
+
+It is highly discouraged, but uids can be shared between multiple packages using the
+`android:sharedUserId` manifest attribute.
+
+### class UserHandle
+
+A wrapper for userId. Used esp. in public APIs instead of `int userId` as it clearly distinguishes
+from uid.
+
+## Security model
+
+Multiple packages can share an uid by using `android:sharedUserId` manifest attribute. If packages
+share a uid they can run in the same process via `android:process` manifest attribute. Further file
+level access is also tracked by uid. Hence any security or privacy mechanism needs to be built on
+a uid granularity.
+
+On the other hand apps belonging to the same user cannot see each others files. They can only
+interact via activity launches, broadcasts, providers, and service bindings. All of them can be be
+protected by [permissions](../permission/Permissions.md). Hence any new general communication
+mechanism should be access controlled by permissions.
+
+## Lifecycle
+
+A system service should deal with users being started and stopped by overriding
+`SystemService.onSwitchUser` and `SystemService.onStopUser`.
+
+If users profiles become inactive the system should stop all apps of this profile from interacting
+with other apps or the system.
+
+Another important lifecycle event is `onUnlockUser`. Only for unlocked user profiles you can access
+all data, e.g. which packages are installed.
+
+You only want to deal with user profiles that
+
+- are in the profile group of the foreground user
+- the user profile is unlocked and not yet stopped
diff --git a/core/java/android/permission/Permissions.md b/core/java/android/permission/Permissions.md
new file mode 100644
index 0000000..e62bd0a
--- /dev/null
+++ b/core/java/android/permission/Permissions.md
@@ -0,0 +1,832 @@
+<!--
+ 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
+ -->
+
+# Android permissions for system developers
+
+This document targets system developers. App developers should refer to the [public
+ documentation](https://developer.android.com/guide/topics/permissions/overview).
+
+## Definitions
+
+Each app (often called package) has a unique name called package name. Each package has a manifest
+file describing properties of the package. The android system server is in a special package named
+"android".
+
+When a package gets installed the package is (usually) assigned a unique identifier called [uid
+](../os/Users.md#int-uid).
+This is the same as a uid in Linux, but this often leads to confusion. It is easiest to see a uid
+as a unique identifier for a package.
+
+Usually an app is running in a container called a process. Each process has a unique id called
+pid, but unlike the uid the pid changes each time the process is restarted and app that are not
+currently running don't have a pid. The process container makes sure that other apps cannot
+negatively interact with an app. Processes can only interact via controlled interactions called
+remote procedure calls (RPCs). Android’s RPC mechanism is called _Binder_.
+
+As no app code can be trusted the permission need to be checked on the receiving side of the
+Binder call.
+
+For more details please take a look at [Android's security model](../os/Users.md#security-model).
+
+## Permissions for regular apps
+
+### Install time permissions
+
+The purpose of install time permissions is to control access to APIs where it does not makes sense
+to involve the user. This can be either because the API is not sensitive, or because additional
+checks exist.
+
+#### Defining a permission
+
+Any package can define a permission. For that it simply adds an entry in the manifest file
+`<permission android:name="com.example.myapp.myfirstpermission" />`
+
+Any package can do this, including the system package. When talking about [permissions for system
+ apps](#permissions-for-system-apps) we will see that it is important which package defines a
+permission.
+
+It is common good practice to prefix the permission name with the package name to avoid collisions.
+
+#### Requesting a permission
+
+Any app can request any permission via adding an entry in the manifest file like
+`<uses-permission android:name="com.example.myapp.myfirstpermission" />`
+
+A requested permission does not necessarily mean that the permission is granted. When and how a
+permission is granted depends on the protection level of the permission. If no protection level is
+set, the permission will always be granted. Such "normal" permissions can still be useful as it
+will be easy to find apps using a certain functionality on app stores and by checking `dumpsys
+package`.
+
+#### Checking a permission
+
+`Context.checkPermission(permission, pid, uid)` returns if the pid/uid has the permission. By far
+the most common case is to check the permission on the receiving end of a binder call. In this case
+the pid can be read as `Binder.callingPid()` and the uid as `Binder.callingUid()`. The uid is a
+mandatory argument as permissions are maintained per uid. The pid can be set to -1
+if not pid is available. The context class contains handy wrappers for `checkPermission`, such as
+`enforeCallingPermission` which calls checkPermission with `Binder.callingPid`/`Binder.callingUid`
+and throws a SecurityException when the permission is not granted.
+
+#### Verifying an app has an install time permission
+
+In `dumpsys package my.package.name` there are two sections. In requested permissions all
+permissions of the `uses-permission` tags are listed. In install permission the permissions with
+their grant state are listed. If an install time permission is not listed here, it is not granted.
+
+```
+Packages:
+ Package [com.android.packageinstaller] (2eb7062):
+ userId=10071
+ [...]
+ requested permissions:
+ android.permission.MANAGE_USERS
+ android.permission.INSTALL_PACKAGES
+ android.permission.DELETE_PACKAGES
+ android.permission.READ_INSTALL_SESSIONS
+ android.permission.RECEIVE_BOOT_COMPLETED
+ android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS
+ android.permission.USE_RESERVED_DISK
+ android.permission.UPDATE_APP_OPS_STATS
+ android.permission.MANAGE_APP_OPS_MODES
+ android.permission.INTERACT_ACROSS_USERS_FULL
+ android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME
+ android.permission.PACKAGE_USAGE_STATS
+ install permissions:
+ android.permission.USE_RESERVED_DISK: granted=true
+ android.permission.INSTALL_PACKAGES: granted=true
+ android.permission.RECEIVE_BOOT_COMPLETED: granted=true
+ android.permission.INTERACT_ACROSS_USERS_FULL: granted=true
+ android.permission.PACKAGE_USAGE_STATS: granted=true
+ android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME: granted=true
+ android.permission.READ_INSTALL_SESSIONS: granted=true
+ android.permission.MANAGE_USERS: granted=true
+ android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS: granted=true
+ android.permission.MANAGE_APP_OPS_MODES: granted=true
+ android.permission.UPDATE_APP_OPS_STATS: granted=true
+ android.permission.DELETE_PACKAGES: granted=true
+```
+
+#### End-to-end: Protecting an RPC call via a permission
+
+##### Service Manifest
+
+```xml
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.example.myservice">
+ <!-- Define a permission -->
+ <permission android:name="com.android.example.myservice.MY_PERMISSION" />
+ <application>
+ <service android:name=".MyService" android:exported="true" />
+ </application>
+</manifest>
+```
+
+##### Service code
+
+```kotlin
+class MyService : Service() {
+ override fun onBind(intent: Intent?): IBinder? {
+ return object : IMyService.Stub() {
+ override fun doSomething() {
+ // Verify that calling UID has the permission
+ enforceCallingPermission(
+ "com.android.example.myservice.MY_PERMISSION",
+ "Need to hold permission"
+ )
+ // do something
+ }
+ }.asBinder()
+ }
+}
+```
+
+##### Caller Manifest
+
+```xml
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.example.myapp">
+ <!-- request a permission -->
+ <uses-permission android:name="com.android.example.myservice.MY_PERMISSION" />
+ <application />
+</manifest>
+```
+
+### Runtime permissions
+
+Runtime permission must be granted by the user during runtime. This is needed if the API protects
+data or functionality that is sensitive for the user. E.g. the users current location is protected
+by a runtime permission.
+
+Users want a system that is secure and privacy focused by default. User can also often not make a
+good choice when asked at the wrong time without enough context. Hence in general runtime
+permissions should be avoided and the API should be built in a way where no private data needs to be
+leaked.
+
+#### Defining a runtime permission
+
+Runtime permissions are defined in the same way as install time permissions. To tag them as runtime
+permissions the `protectionLevel` needs to be set to dangerous. Dangerous is a synonym for
+runtime permissions in the Android platform.
+
+```xml
+<uses-permission android:name="com.example.myapp.myfirstruntimepermission"
+ android:protectionLevel="dangerous" />
+```
+
+#### Requesting a runtime permission
+
+Similar to install time permissions any app can request a runtime permission by adding the
+`<uses-permission android:name="com.example.myapp.myfirstruntimepermission" />`
+to the manifest.
+
+By default runtime permissions are not granted. The app needs to call `Activity.requestPermissions`
+during runtime to ask the user for the permission. The user might then grant or deny and once the
+decision is made the activity is called by via `Activity.onPermissionGranted`.
+
+During development and testing a runtime permission can be granted via the `pm` shell command or by
+using the `UiAutomator.grantRuntimePermission` API call. Please note that this does _not_ grant the
+[app-op](#runtime-permissions-and-app-ops) synchronously. Unless the app needs to test the actual
+permission grant flow it is recommended to grant the runtime permissions during install using
+`adb install -g /my/package.apk`.
+
+#### Checking a runtime permission
+
+For runtime permissions defined by a 3rd party apps it is fine to check a runtime
+permission like an install time permission. For system defined permissions you need to check all
+runtime permissions by using the `PermissionChecker` utility. It is good practice to use the tool
+anywhere possible.
+
+The permission checker might return `PERMISSION_DENIED_APP_OP` which should lead to a silent
+failure. This can only happen for system defined runtime permissions.
+
+##### Runtime permissions and app-ops
+
+> See [App-ops](../app/AppOps.md).
+
+The PermissionChecker code fundamentally looks like this:
+
+```kotlin
+class PermissionChecker {
+ fun checkCallingPermission(context: Context, permission: String) {
+ if (isRuntimePermission(permission)) {
+ if (context.checkPermission(uid, permission) == DENIED) {
+ return PERMISSION_DENIED
+ }
+
+ val appOpOfPermission = AppOpsManager.permissionToOp(permission)
+ if (appOpOfPermission == null) {
+ // not platform defined
+ return PERMISSION_GRANTED
+ }
+
+ val appOpMode = appOpsManager.noteOp(appOpOfPermission)
+ if (appOpMode == AppOpsManager.MODE_ALLOWED) {
+ return PERMISSION_GRANTED
+ } else {
+ return PERMISSION_DENIED_APP_OP
+ }
+ } else {
+ return PERMISSION_DENIED
+ }
+ }
+}
+```
+
+For each platform defined runtime permission there is a matching app-op. When calling
+`AppOpsManager.noteOp` this returns either `MODE_ALLOWED` or `MODE_IGNORED`.
+
+This value is then used to decide between `PERMISSION_DENIED_APP_OP` and `PERMISSION_GRANTED`.
+
+The primary purpose of the special `PERMISSION_DENIED_APP_OP` state was to support apps targeting an
+SDK lower than 23. These apps do not understand the concept of denied runtime permissions. Hence
+they would crash when getting a `SecurityException`. To protect the users' privacy while still not
+crashing the app the special `PERMISSION_DENIED_APP_OP` mandates that the API should somehow
+silently fail.
+
+A secondary use case of the `AppOpsManager.noteOp` calls is to
+[track](../app/AppOps.md#Appops-for-tracking) which apps perform what runtime protected actions.
+
+#### Verifying an app has a runtime time permission
+
+In `dumpsys package my.package.name` the runtime permissions are listed per uid. I.e. different
+users might have different runtime permission grants and shared uids share a grant-set. If a runtime
+permission is listed as requested but not in the runtime permission section it is in it’s initial
+state, i.e. not granted.
+
+```
+Packages:
+ Package [com.google.android.GoogleCamera] (ccb6af):
+ userId=10181
+ [...]
+ requested permissions:
+ android.permission.ACCESS_COARSE_LOCATION
+ android.permission.ACCESS_FINE_LOCATION
+ android.permission.ACCESS_NETWORK_STATE
+ android.permission.ACCESS_NOTIFICATION_POLICY
+ android.permission.ACCESS_WIFI_STATE
+ android.permission.BIND_WALLPAPER
+ android.permission.CAMERA
+ android.permission.CHANGE_WIFI_STATE
+ android.permission.INTERNET
+ android.permission.GET_PACKAGE_SIZE
+ android.permission.NFC
+ android.permission.READ_SYNC_SETTINGS
+ android.permission.RECEIVE_BOOT_COMPLETED
+ android.permission.RECORD_AUDIO
+ android.permission.SET_WALLPAPER
+ android.permission.USE_CREDENTIALS
+ android.permission.VIBRATE
+ android.permission.WAKE_LOCK
+ android.permission.WRITE_EXTERNAL_STORAGE [ ... ]
+ android.permission.WRITE_SETTINGS
+ android.permission.WRITE_SYNC_SETTINGS
+ com.google.android.elmyra.permission.CONFIGURE_ASSIST_GESTURE
+ com.google.android.providers.gsf.permission.READ_GSERVICES
+ android.permission.FOREGROUND_SERVICE
+ com.google.android.googlequicksearchbox.permission.LENSVIEW_BROADCAST
+ android.permission.READ_EXTERNAL_STORAGE [ ... ]
+ [...]
+ User 0: [ ... ]
+ overlay paths:
+ runtime permissions:
+ android.permission.ACCESS_FINE_LOCATION: granted=false [ ... ]
+ android.permission.READ_EXTERNAL_STORAGE: granted=true [ ... ]
+ android.permission.ACCESS_COARSE_LOCATION: granted=false [ ... ]
+ android.permission.CAMERA: granted=true [ ... ]
+ android.permission.WRITE_EXTERNAL_STORAGE: granted=true [ ... ]
+ android.permission.RECORD_AUDIO: granted=true[ ... ]
+```
+
+#### End-to-end: Protecting an RPC call via a runtime permission
+
+##### Service Manifest
+
+```xml
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.example.myservice">
+ <!-- Define a runtime permission -->
+ <permission android:name="com.android.example.myservice.MY_RUNTIME_PERMISSION"
+ android:protectionLevel="dangerous" />
+ <application>
+ <service android:name=".MyService" android:exported="true" />
+ </application>
+</manifest>
+```
+
+##### Service code
+
+```kotlin
+class MyService : Service() {
+ override fun onBind(intent: Intent?): IBinder? {
+ return object : IMyService.Stub() {
+ override fun doSomething(callingPackage: String?, callingFeatureId: String?) {
+ Objects.requireNonNull(callingPackageName)
+
+ // Verify that calling UID has the permission
+ when (run {
+ PermissionChecker.checkCallingPermission(
+ this@MyService,
+ "com.android.example.myservice.MY_RUNTIME_PERMISSION",
+ callingPackageName,
+ callingFeatureId,
+ "Did something"
+ )
+ }) {
+ PERMISSION_GRANTED -> /* do something */
+ PERMISSION_DENIED_APP_OP -> /* silent failure, do nothing */
+ else -> throw SecurityException(
+ "Cannot do something as caller is missing "
+ + "com.android.example.myservice.MY_RUNTIME_PERMISSION"
+ )
+ }
+ }
+ }.asBinder()
+ }
+}
+```
+
+##### Caller Manifest
+
+```xml
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.example.myapp">
+ <!-- request a permission -->
+ <uses-permission android:name="com.android.example.myservice.MY_RUNTIME_PERMISSION" />
+ <application />
+</manifest>
+```
+
+##### Caller code
+
+```kotlin
+class MyActivity : Activity {
+ fun callDoSomething() {
+ if (checkSelfPermission("com.android.example.myservice.MY_RUNTIME_PERMISSION") == PERMISSION_DENIED) {
+ // Interrupt operation and request permission
+ requestPermissions(arrayOf("com.android.example.myservice.MY_RUNTIME_PERMISSION"), 23)
+ } else {
+ myService.doSomething(this@MyActivity.opPackageName, this@MyActivity.featureId)
+ }
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array<String>,
+ grantResults: IntArray
+ ) {
+ if (requestCode == 23 && grantResults[0] == PERMISSION_GRANTED) {
+ // Finish operation
+ callDoSomething()
+ }
+ }
+}
+```
+
+#### Restricted permissions
+
+Some runtime permissions are restricted. They are annotated in the platforms `AndroidManifest.xml`
+has `hardRestricted` or `softRestricted`.
+
+Restricted permissions behave uncommon when not whitelisted. When whitelisted the permissions
+behave normally. What uncommon means depends on the whether they are hard or soft restricted.
+
+They can either be whitelisted during upgrade P->Q, but the system or need to be whitelisted by the
+installer via `PackageInstaller.SessionParams.setWhitelistedRestrictedPermissions`. If this method
+is not used all permissions will be whitelisted.
+
+Afterwards the app that originally installed the app can change the whitelisting state via
+`PackageManager.addWhitelistedRestrictedPermission` and
+`PackageManager.removeWhitelistedRestrictedPermission`.
+
+The system tracks the source of the whitelisting by having three different flags
+ `RESTRICTION_SYSTEM_EXEMPT`, `RESTRICTION_UPGRADE_EXEMPT`, and `RESTRICTION_INSTALLER_EXEMPT`,
+
+The flags can be checked in `dumpsys package my.package.name`
+
+```
+User 0:
+ [...]
+ runtime permissions:
+ android.permission.READ_EXTERNAL_STORAGE: granted=false, flags=[ RESTRICTION_UPGRADE_EXEMPT ]
+ android.permission.ACCESS_FINE_LOCATION: granted=true, flags=[ RESTRICTION_SYSTEM_EXEMPT|RESTRICTION_UPGRADE_EXEMPT ]
+```
+
+##### Hard restricted
+
+Hard restricted permissions need to be whitelisted to be grant-able.
+
+##### Soft restricted
+
+The behavior of non-whitelisted soft restricted permissions is not uniform. The behavior is
+defined in the `SoftRestrictedPermissionPolicy`.
+
+#### System fixed permission
+
+Some runtime permissions are required for normal operation of the device. In this case the system
+can grant the permission as `SYSTEM_FIXED`. In this case the permission can be seen in the
+[permission management settings](#settings) but cannot be revoked by the user.
+
+The flag can be checked in `dumpsys package my.package.name`
+```
+User 0:
+ [...]
+ runtime permissions:
+ android.permission.READ_EXTERNAL_STORAGE: granted=true, flags=[ SYSTEM_FIXED|GRANTED_BY_DEFAULT ]
+```
+
+#### Background access
+
+Whether the app is currently visible to the user is reflected in the `ActivityManager`'s proc state.
+There is a lot of granularity to this, but runtime permissions are using the [app-ops services'
+](../app/AppOps.md) definition of foreground and background.
+
+Most runtime permissions are not affected by foreground/background-ness. Microphone and Camera are
+foreground-only while Location is usually foreground-only, but background access can be added by
+granting the `ACCESS_BACKGROUND_LOCATION` modifier runtime permission.
+
+##### Microphone and Camera
+
+Currently these only allow access while in the app is in foreground. There is a manual whitelist
+for e.g. the voice interaction service.
+
+This is currently (Mar 2020) reworked and will behave like [location](#location) soon.
+
+##### Location
+
+As described [above](#runtime-permissions-and-app-ops) the app-op mode for granted permissions is
+`MODE_ALLOWED` to allow access or `MODE_IGNORED` to suppress access.
+
+The important case is the case where the permission is granted and the app-op is `MODE_IGNORED`. In
+the case of location this state causes the `LocationManagerService` to stop delivering locations to
+the app. This is not a breaking behavior as the same scenarios happens if e.g. no satellites
+could be found.
+
+This behavior is used to implement the foregound/background behavior for location. If the app is
+in the foreground the app-op mode is `MODE_ALLOWED` and works normally. If the app goes into
+background the app-op mode changes to `MODE_IGNORED`. This means that locations are delivered while
+the app is in foreground and while the app is background, the app won't get any locations.
+
+The automatic switching between `MODE_ALLOWED` and `MODE_IGNORED` is done inside of
+ [`AppOpsManager`](../app/AppOps.md#foreground).
+
+Background access can be enabled by also granting the `ACCESS_BACKGROUND_LOCATION` to the app. In
+this case the app-op mode will always be `MODE_ALLOWED`.
+
+#### UI
+
+##### Granting
+
+An app following the best practices does not ask for any runtime permissions until absolutely
+needed. Once needed the request should be made in context. I.e. the user should understand from the
+current state of the app and the user's action why the request is made. E.g. if the user presses
+a "show me the next ATM"-button the user is most likely expecting a request for the location
+permission.
+
+This is central premise to the runtime permission UI. It is the app's responsibility to avoid
+showing permission requests dialogs to the user which might get denied. These dialogs are not
+meant to be user-choices, they are meant to be user-confirmations.
+
+Hence any denied permission dialog is probably due to the app asking for permissions the user
+does not expect. If too many permission requests get denied the app is apparently trying to get
+more than the user wants to give to the app. In this case the permission gets permanently denied
+and all future requests will be denied automatically without showing a UI.
+
+`Context.requestPermission` calls for more than one permission are allowed and might result in
+multiple dialogs in sequence. This might make sense for e.g. getting microphone and camera
+permission when starting a video call.
+
+Each time the the user makes a choice (either to grant or the deny) a permission request the
+permission is marked as `USER_SET`. If a permission gets permanently denied the permission is marked
+as `USER_FIXED`.
+
+This can be found in `dumpsys package my.package.name`
+```
+User 0:
+ [...]
+ runtime permissions:
+ android.permission.READ_EXTERNAL_STORAGE: granted=false, flags=[ USER_SET|USER_FIXED ]
+ android.permission.ACCESS_FINE_LOCATION: granted=true, flags=[ USER_SET ]
+```
+
+##### Settings
+
+By far most interactions with the permission system are via the [permission grant flow](#granting).
+The main purpose of the permission settings is to show the user the previous choices and allow
+the user to revisit previous choices. In reality few users do that.
+
+##### Grouping
+
+There are too many runtime permissions for the user to individually manage. Hence the UI bundles the
+permissions into groups. **Apps should never assume the grouping**. The grouping might change
+with SDK updates, but also at any other time. Certain form factors or locales might use other
+permission models and sometimes some of the permissions of a group cannot be granted for various
+reasons. The grouping is defined inside the permission controller app.
+
+If two permissions belong to a group and the first permission is already granted the second one
+will be granted on request of the app without user interaction. For that reason a permission
+group with at least one individual permission granted will show up as granted in the UI.
+
+##### Alternate permission management
+
+It is not allowed to build alternate permission management UIs. While restricting innovation is not
+a good choice this is a required one to enforce a consistent, predictable, but flexible permission
+model for users and app developers.
+
+Further some data needed for permission management (e.g. the grouping) is not available outside
+the permission controller app.
+
+Hence all permission management UI needs to be integrated with AOSP.
+
+#### Pre granting
+
+Runtime permissions protect user private data. It is a violation of user trust to give the data
+to an app without explicit user consent (i.e. the user [granting](#granting) the permission
+). Still the user expects certain functionality (e.g. receiving a phone call) to work out of the
+box.
+
+Hence the `DefaultPermissionGrantPolicy` and roles allow to grant permission without the user
+. The default permission grant policy grants permissions for three categories of apps
+- Apps running in well defined [uids](../os/Users.md#int-uid) as they are considered as part of
+ the platform
+- Apps that are in certain predefined categories, e.g. the browser and the SMS app. This is
+ meant for the most basic phone functionality, not for all pre-installed apps.
+- Apps that are explicitly mentioned as a pre-grant-exceptions. This is meant to be used for setup
+ and other highly critical use cases, not to improve the user experience. The exceptions are listed
+ in xml files in `etc/` and follow the following syntax
+```xml
+<exceptions>
+ <exception package="my.package.name">
+ <permission name="android.permission.ACCESS_FINE_LOCATION" fixed="false"/>
+ </exception>
+</exceptions>
+```
+
+Pre-granted runtime permissions can still be revoked by the user in [settings](#settings) unless
+they are granted as `SYSTEM_FIXED`.
+
+Whether a permission was granted by the default can be checked in the permission flags of
+`dumpsys package my.package.name`
+
+```
+User 0:
+ [...]
+ runtime permissions:
+ android.permission.ACCESS_FINE_LOCATION: granted=true, flags=[ GRANTED_BY_DEFAULT ]
+```
+
+### 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
+
+- define a permission in the platform as `signature`
+- protect a service in an app by this permission using the `android:permission` attribute of the
+ `<service>` tag
+
+Then it is guaranteed that only the system can bind to such service. This is used for services
+that provide extensions to platform functionality, such as auto-fill services, print services, and
+accessibility services.
+
+This does not work for app-op or runtime permissions as the way to check these permissions is
+more complex than install time permissions.
+
+## Permissions for system apps
+
+System apps need to integrate deeper with the system than regular apps. Hence they need to be
+able to call APIs not available to other apps. This is implemented by granting permissions to
+these system apps and then enforcing the permissions in the API similar to other [install time
+permissions](#checking-a-permission).
+
+System apps are not different from regular apps, but the protection levels (e.g.
+[privileged](#privileged-permissions), [preinstalled](#preinstalled-permissions)) mentioned in this
+section are more commonly used by system apps.
+
+### Multiple permission levels
+
+It is possible to assign multiple protection levels to a permission. Very common combinations are
+for example adding `signature` to all permissions to make sure the platform signed apps can be
+granted the permission, e.g. `privileged|signature`.
+
+The permission will be granted if the app qualifies for _any_ of the permission levels.
+
+### App-op permissions
+
+> See [App-ops](../app/AppOps.md).
+
+App-op permissions are user-switchable permissions that are not runtime permissions. This should
+be used for permissions that are really only meant to be ever granted to a very small amount of
+apps. Traditionally granting these permissions is intentionally very heavy weight so that the
+user really needs to understand the use case. For example one use case is the
+`INTERACT_ACROSS_PROFILES` permission that allows apps of different
+[user profiles](../os/Users.md#user-profile) to interact. Of course this is breaking a very basic
+security container and hence should only every be granted with a lot of care.
+
+**Warning:** Most app-op permissions follow this logic, but most of them also have exceptions
+and special behavior. Hence this section is a guideline, not a rule.
+
+#### Defining an app-op permission
+
+Only the platform can reasonably define an app-op permission. The permission is defined in the
+platforms manifest using the `appop` protection level
+
+```xml
+<manifest package="android">
+ <permission android:name="android.permission.MY_APPOP_PERMISSION"
+ android:protectionLevel="appop|signature" />
+</manifest>
+```
+
+Almost always the protection level is app-op | something else, like
+[signature](#signature-permissions) (in the case above) or [privileged](#privileged-permissions).
+
+#### Checking a app-op permission
+
+The `PermissionChecker` utility can check app-op permissions with the [same syntax as runtime
+permissions](#checking-a-runtime-permission).
+
+The permission checker internally follows this flow
+
+```kotlin
+class PermissionChecker {
+ fun checkCallingPermission(context: Context, permission: String) {
+ if (isAppOpPermission(permission)) {
+ val appopOfPermission = AppOpsManager.permissionToOp(permission)
+ if (appopOfPermission == null) {
+ // not platform defined
+ return PERMISSION_DENIED
+ }
+
+ val appopMode = appOpsManager.noteOp(appopOfPermission)
+ when (appopMode) {
+ AppOpsManager.MODE_ALLOWED -> return PERMISSION_GRANTED
+ AppOpsManager.MODE_IGNORED -> return PERMISSION_DENIED
+ AppOpsManager.MODE_DEFAULT -> {
+ if (context.checkPermission(uid, permission) == GRANTED) {
+ return PERMISSION_GRANTED
+ } else {
+ return PERMISSION_DENIED
+ }
+ }
+ }
+ } else {
+ return PERMISSION_DENIED
+ }
+ }
+}
+```
+
+#### Granting a app-op permission
+
+The permission's grant state is only considered if the app-op's mode is `MODE_DEFAULT`. This
+allows to have default grants while still being overridden by the app-op.
+
+The permission is then granted by setting the app-op mode. This is usually done via dedicated APIs
+for each use cases. Similarly whether and how an app can request the permission is different for
+each app-op permission.
+
+When implementing a new app-op permission, make sure to set the app-op mode using `AppOpsManager
+.setUidMode` to make sure the permission is granted on the uid as this is the security domain.
+
+During development app-ops can be grated to app via the `appops set` shell command. E.g.
+
+```
+adb shell appops set 10187 INTERACT_ACROSS_PROFILES allow
+```
+
+sets the `INTERACT_ACROSS_PROFILES` app-op for uid 10187 to allow thereby granting apps in this
+uid the ability to interact across profiles.
+
+##### UI
+
+Most UIs for app-op permissions are in the "Special app access" section of the settings app.
+
+In most cases the permission should only be granted with the user's explicit agreement, usually by
+allowing the app to directly open the "Special app access" page for this permission and app.
+
+To repeat: this is a guideline for app-op permissions and there are many exceptions.
+
+### Signature permissions
+
+Only apps signed with the defining app's certificate will be granted the permission. This is
+used to restrict APIs to apps of the same developer.
+
+This is frequently used to restrict permissions defined by the platform to apps also signed with
+the platform's certificate. As this is a very tight restriction this is recommended for
+permissions that are only used by apps built out of AOSP which are signed with the platform
+certificate.
+
+Please note that OEMs sign their platform them self. I.e. OEMs can implement new apps using these
+permissions. It is unlikely that 3rd party apps will be able to use APIs protected by signature
+permissions as they are usually not signed with the platform certificate.
+
+Such permissions are defined and checked like an install time permission.
+
+### Preinstalled permissions
+
+This means that the app has to be pre-installed. There is no restriction what apps are pre-installed
+on a particular device install there. Hence it can be really any app including 3rd party apps.
+
+Hence this permission level is discouraged unless there are
+[further restrictions](#restricted-by-tests).
+
+Such permissions are defined and checked like an install time permission.
+
+### Privileged permissions
+
+This means that the app has to be pre-installed and in the `system/priv` directory in the
+filesystem. There is no restriction what apps are in this directory on a particular device
+install there. Hence it can be really any app including 3rd party apps.
+
+An app is only ever granted privileged permissions requested by the pre-installed apk. I.e.
+privileged permissions added in updates will never be granted.
+
+Hence this permission level is discouraged unless there are
+[further restrictions](#restricted-by-tests).
+
+Such permissions are defined and checked like an install time permission.
+
+#### Restricted by tests
+
+As all apps that might get preinstalled or privilidged permissions need to be pre-installed and new
+images need to pass compliance tests it is possible to use a test to whitelist the apps that can
+request the permission.
+
+Example of such a test:
+```kotlin
+/* Add new whitelisted packages to this list */
+private val whitelistedPkgs = listOf("my.whitelisted.package")
+
+@Test
+fun onlySomeAppsAreAllowedToHavePermissionGranted() {
+ assertThat(whitelistedPkgs).containsAllIn(
+ context.packageManager.getInstalledPackages(MATCH_ALL)
+ .filter { pkg ->
+ context.checkPermission(android.Manifest.permission.MY_PRIVILEGED_PERMISSION, -1,
+ pkg.applicationInfo.uid) == PERMISSION_GRANTED
+ /* The permission is defined by the system and hence granted to it */
+ }.filter { pkg -> pkg.applicationInfo.uid != SYSTEM_UID }
+ .map { it.packageName }
+ )
+}
+```
+
+#### Whitelist
+
+As mentioned above it is not suggested, but still common practice to install 3rd party apps as
+privilidged. To verify and restrict which privilidged permissions those apps get granted all
+privilidged permissions need to be explicitly whitelisted in a file `/etc`.
+
+```xml
+<permissions>
+ <privapp-permissions package="my.privileged.package">
+ <!-- allow the app to request a permission -->
+ <permission name="android.permission.MY_PRIVILEGED_PERMISSION"/>
+
+ <!-- Even though the app requests the permission, do not grant it -->
+ <deny-permission name="android.permission.MY_OTHER_PRIVILEGED_PERMISSION"/>
+ </privapp-permissions>
+</permissions>
+```
+
+If the pre-installed apk of app requests a privileged permission that is not mentioned in any
+whitelist or that is not denied the system will refuse to boot. As mentioned above privileged
+permissions added in updates to the pre-installed app will never be granted.
+
+### Limited permissions
+
+E.g. installer, wellbeing, documenter, etc... This allows the system to restrict the permission to a
+well defined app or set of apps. It is possible to add new types in `PackageManagerService`.
+
+Which apps qualify for such a permission level is flexible and custom for each such level. Usually
+they refer to a single or small set of apps, usually - but not always - apps defined in AOSP.
+
+These permissions are defined and checked like an install time permission.
+
+### Development permissions
+
+> Not recommended
+
+By adding the `development` protection level to any permissions the permission can be granted via
+the `pm grant` shell command. This appears to be useful for development and testing, but it is very
+highly discouraged. Any user can grant them permanently via adb, hence adding this tag removes
+all guarantees the permission might otherwise provide.
+
+### Other protection levels
+
+There are other levels (such as `runtime`) but they are for special purposes on should not be
+used by platform developers.
diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java
index 1eb7664..dd2ea81 100644
--- a/core/java/android/provider/BlockedNumberContract.java
+++ b/core/java/android/provider/BlockedNumberContract.java
@@ -16,7 +16,6 @@
package android.provider;
import android.annotation.IntDef;
-import android.annotation.SystemApi;
import android.annotation.WorkerThread;
import android.content.Context;
import android.net.Uri;
@@ -240,7 +239,6 @@
* blocked.
* @hide
*/
- @SystemApi
public static final int STATUS_NOT_BLOCKED = 0;
/**
@@ -248,7 +246,6 @@
* because it is in the list of blocked numbers maintained by the provider.
* @hide
*/
- @SystemApi
public static final int STATUS_BLOCKED_IN_LIST = 1;
/**
@@ -256,7 +253,6 @@
* because it is from a restricted number.
* @hide
*/
- @SystemApi
public static final int STATUS_BLOCKED_RESTRICTED = 2;
/**
@@ -264,7 +260,6 @@
* because it is from an unknown number.
* @hide
*/
- @SystemApi
public static final int STATUS_BLOCKED_UNKNOWN_NUMBER = 3;
/**
@@ -272,7 +267,6 @@
* because it is from a pay phone.
* @hide
*/
- @SystemApi
public static final int STATUS_BLOCKED_PAYPHONE = 4;
/**
@@ -280,14 +274,12 @@
* because it is from a number not in the users contacts.
* @hide
*/
- @SystemApi
public static final int STATUS_BLOCKED_NOT_IN_CONTACTS = 5;
/**
* Integer reason indicating whether a call was blocked, and if so why.
* @hide
*/
- @SystemApi
public static final String RES_BLOCK_STATUS = "block_status";
/** @hide */
@@ -298,31 +290,6 @@
"can_current_user_block_numbers";
/** @hide */
- @SystemApi
- public static final String METHOD_NOTIFY_EMERGENCY_CONTACT = "notify_emergency_contact";
-
- /** @hide */
- public static final String METHOD_END_BLOCK_SUPPRESSION = "end_block_suppression";
-
- /** @hide */
- @SystemApi
- public static final String METHOD_SHOULD_SYSTEM_BLOCK_NUMBER = "should_system_block_number";
-
- /** @hide */
- public static final String METHOD_GET_BLOCK_SUPPRESSION_STATUS =
- "get_block_suppression_status";
-
- /** @hide */
- public static final String METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION =
- "should_show_emergency_call_notification";
-
- /** @hide */
- public static final String METHOD_GET_ENHANCED_BLOCK_SETTING = "get_enhanced_block_setting";
-
- /** @hide */
- public static final String METHOD_SET_ENHANCED_BLOCK_SETTING = "set_enhanced_block_setting";
-
- /** @hide */
public static final String RES_CAN_BLOCK_NUMBERS = "can_block";
/** @hide */
@@ -439,11 +406,26 @@
public static final String ACTION_BLOCK_SUPPRESSION_STATE_CHANGED =
"android.provider.action.BLOCK_SUPPRESSION_STATE_CHANGED";
+ public static final String METHOD_NOTIFY_EMERGENCY_CONTACT = "notify_emergency_contact";
+
+ public static final String METHOD_END_BLOCK_SUPPRESSION = "end_block_suppression";
+
+ public static final String METHOD_SHOULD_SYSTEM_BLOCK_NUMBER = "should_system_block_number";
+
+ public static final String METHOD_GET_BLOCK_SUPPRESSION_STATUS =
+ "get_block_suppression_status";
+
+ public static final String METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION =
+ "should_show_emergency_call_notification";
+
public static final String RES_IS_BLOCKING_SUPPRESSED = "blocking_suppressed";
public static final String RES_BLOCKING_SUPPRESSED_UNTIL_TIMESTAMP =
"blocking_suppressed_until_timestamp";
+ public static final String METHOD_GET_ENHANCED_BLOCK_SETTING = "get_enhanced_block_setting";
+ public static final String METHOD_SET_ENHANCED_BLOCK_SETTING = "set_enhanced_block_setting";
+
/* Preference key of block numbers not in contacts setting. */
public static final String ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED =
"block_numbers_not_in_contacts_setting";
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index a80153d..327bca2 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -1081,7 +1081,7 @@
// signed with platform signature can hold MANAGE_DOCUMENTS, we are going to check for
// MANAGE_DOCUMENTS or associated URI permission here instead
final Uri rootUri = extras.getParcelable(DocumentsContract.EXTRA_URI);
- enforceWritePermissionInner(rootUri, getCallingPackage(), getCallingFeatureId(),
+ enforceWritePermissionInner(rootUri, getCallingPackage(), getCallingAttributionTag(),
null);
final String rootId = DocumentsContract.getRootId(rootUri);
@@ -1103,8 +1103,8 @@
enforceTree(documentUri);
if (METHOD_IS_CHILD_DOCUMENT.equals(method)) {
- enforceReadPermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
- null);
+ enforceReadPermissionInner(documentUri, getCallingPackage(),
+ getCallingAttributionTag(), null);
final Uri childUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI);
final String childAuthority = childUri.getAuthority();
@@ -1116,8 +1116,8 @@
&& isChildDocument(documentId, childId));
} else if (METHOD_CREATE_DOCUMENT.equals(method)) {
- enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
- null);
+ enforceWritePermissionInner(documentUri, getCallingPackage(),
+ getCallingAttributionTag(), null);
final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
@@ -1131,8 +1131,8 @@
out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);
} else if (METHOD_CREATE_WEB_LINK_INTENT.equals(method)) {
- enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
- null);
+ enforceWritePermissionInner(documentUri, getCallingPackage(),
+ getCallingAttributionTag(), null);
final Bundle options = extras.getBundle(DocumentsContract.EXTRA_OPTIONS);
final IntentSender intentSender = createWebLinkIntent(documentId, options);
@@ -1140,8 +1140,8 @@
out.putParcelable(DocumentsContract.EXTRA_RESULT, intentSender);
} else if (METHOD_RENAME_DOCUMENT.equals(method)) {
- enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
- null);
+ enforceWritePermissionInner(documentUri, getCallingPackage(),
+ getCallingAttributionTag(), null);
final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
final String newDocumentId = renameDocument(documentId, displayName);
@@ -1165,8 +1165,8 @@
}
} else if (METHOD_DELETE_DOCUMENT.equals(method)) {
- enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
- null);
+ enforceWritePermissionInner(documentUri, getCallingPackage(),
+ getCallingAttributionTag(), null);
deleteDocument(documentId);
// Document no longer exists, clean up any grants.
@@ -1176,9 +1176,9 @@
final Uri targetUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI);
final String targetId = DocumentsContract.getDocumentId(targetUri);
- enforceReadPermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
- null);
- enforceWritePermissionInner(targetUri, getCallingPackage(), getCallingFeatureId(),
+ enforceReadPermissionInner(documentUri, getCallingPackage(),
+ getCallingAttributionTag(), null);
+ enforceWritePermissionInner(targetUri, getCallingPackage(), getCallingAttributionTag(),
null);
final String newDocumentId = copyDocument(documentId, targetId);
@@ -1202,11 +1202,11 @@
final Uri targetUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI);
final String targetId = DocumentsContract.getDocumentId(targetUri);
- enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
- null);
- enforceReadPermissionInner(parentSourceUri, getCallingPackage(), getCallingFeatureId(),
- null);
- enforceWritePermissionInner(targetUri, getCallingPackage(), getCallingFeatureId(),
+ enforceWritePermissionInner(documentUri, getCallingPackage(),
+ getCallingAttributionTag(), null);
+ enforceReadPermissionInner(parentSourceUri, getCallingPackage(),
+ getCallingAttributionTag(), null);
+ enforceWritePermissionInner(targetUri, getCallingPackage(), getCallingAttributionTag(),
null);
final String newDocumentId = moveDocument(documentId, parentSourceId, targetId);
@@ -1228,10 +1228,10 @@
final Uri parentSourceUri = extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI);
final String parentSourceId = DocumentsContract.getDocumentId(parentSourceUri);
- enforceReadPermissionInner(parentSourceUri, getCallingPackage(), getCallingFeatureId(),
- null);
- enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
- null);
+ enforceReadPermissionInner(parentSourceUri, getCallingPackage(),
+ getCallingAttributionTag(), null);
+ enforceWritePermissionInner(documentUri, getCallingPackage(),
+ getCallingAttributionTag(), null);
removeDocument(documentId, parentSourceId);
// It's responsibility of the provider to revoke any grants, as the document may be
@@ -1240,8 +1240,8 @@
final boolean isTreeUri = isTreeUri(documentUri);
if (isTreeUri) {
- enforceReadPermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
- null);
+ enforceReadPermissionInner(documentUri, getCallingPackage(),
+ getCallingAttributionTag(), null);
} else {
getContext().enforceCallingPermission(Manifest.permission.MANAGE_DOCUMENTS, null);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 084f37f..13070a0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -710,10 +710,7 @@
* If not specified, the default behavior is
* {@link android.hardware.biometrics.BiometricManager.Authenticators#BIOMETRIC_WEAK}.
* <p>
- * Output: Returns {@link android.app.Activity#RESULT_CANCELED} if the user already has an
- * authenticator that meets the requirements, or if the device cannot fulfill the request
- * (e.g. does not have biometric hardware). Returns {@link android.app.Activity#RESULT_OK}
- * otherwise. Note that callers should still check
+ * Output: Nothing. Note that callers should still check
* {@link android.hardware.biometrics.BiometricManager#canAuthenticate(int)}
* afterwards to ensure that the user actually completed enrollment.
*/
@@ -2627,7 +2624,7 @@
arg.putBoolean(CALL_METHOD_OVERRIDEABLE_BY_RESTORE_KEY, true);
}
IContentProvider cp = mProviderHolder.getProvider(cr);
- cp.call(cr.getPackageName(), cr.getFeatureId(),
+ cp.call(cr.getPackageName(), cr.getAttributionTag(),
mProviderHolder.mUri.getAuthority(), mCallSetCommand, name, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't set key " + name + " in " + mUri, e);
@@ -2647,7 +2644,7 @@
args.putString(CALL_METHOD_PREFIX_KEY, prefix);
args.putSerializable(CALL_METHOD_FLAGS_KEY, keyValues);
IContentProvider cp = mProviderHolder.getProvider(cr);
- Bundle bundle = cp.call(cr.getPackageName(), cr.getFeatureId(),
+ Bundle bundle = cp.call(cr.getPackageName(), cr.getAttributionTag(),
mProviderHolder.mUri.getAuthority(),
mCallSetAllCommand, null, args);
return bundle.getBoolean(KEY_CONFIG_SET_RETURN);
@@ -2722,14 +2719,14 @@
if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) {
final long token = Binder.clearCallingIdentity();
try {
- b = cp.call(cr.getPackageName(), cr.getFeatureId(),
+ b = cp.call(cr.getPackageName(), cr.getAttributionTag(),
mProviderHolder.mUri.getAuthority(), mCallGetCommand, name,
args);
} finally {
Binder.restoreCallingIdentity(token);
}
} else {
- b = cp.call(cr.getPackageName(), cr.getFeatureId(),
+ b = cp.call(cr.getPackageName(), cr.getAttributionTag(),
mProviderHolder.mUri.getAuthority(), mCallGetCommand, name, args);
}
if (b != null) {
@@ -2799,13 +2796,13 @@
if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) {
final long token = Binder.clearCallingIdentity();
try {
- c = cp.query(cr.getPackageName(), cr.getFeatureId(), mUri,
+ c = cp.query(cr.getPackageName(), cr.getAttributionTag(), mUri,
SELECT_VALUE_PROJECTION, queryArgs, null);
} finally {
Binder.restoreCallingIdentity(token);
}
} else {
- c = cp.query(cr.getPackageName(), cr.getFeatureId(), mUri,
+ c = cp.query(cr.getPackageName(), cr.getAttributionTag(), mUri,
SELECT_VALUE_PROJECTION, queryArgs, null);
}
if (c == null) {
@@ -2898,7 +2895,7 @@
}
// Fetch all flags for the namespace at once for caching purposes
- Bundle b = cp.call(cr.getPackageName(), cr.getFeatureId(),
+ Bundle b = cp.call(cr.getPackageName(), cr.getAttributionTag(),
mProviderHolder.mUri.getAuthority(), mCallListCommand, null, args);
if (b == null) {
// Invalid response, return an empty map
@@ -5543,7 +5540,7 @@
}
arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode);
IContentProvider cp = sProviderHolder.getProvider(resolver);
- cp.call(resolver.getPackageName(), resolver.getFeatureId(),
+ cp.call(resolver.getPackageName(), resolver.getAttributionTag(),
sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_SECURE, null, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e);
@@ -13389,7 +13386,7 @@
}
arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode);
IContentProvider cp = sProviderHolder.getProvider(resolver);
- cp.call(resolver.getPackageName(), resolver.getFeatureId(),
+ cp.call(resolver.getPackageName(), resolver.getAttributionTag(),
sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_GLOBAL, null, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e);
@@ -14364,7 +14361,7 @@
arg.putString(Settings.CALL_METHOD_PREFIX_KEY, createPrefix(namespace));
}
IContentProvider cp = sProviderHolder.getProvider(resolver);
- cp.call(resolver.getPackageName(), resolver.getFeatureId(),
+ cp.call(resolver.getPackageName(), resolver.getAttributionTag(),
sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_CONFIG, null, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't reset to defaults for " + DeviceConfig.CONTENT_URI, e);
@@ -14393,7 +14390,7 @@
arg.putInt(CALL_METHOD_USER_KEY, userHandle);
arg.putParcelable(CALL_METHOD_MONITOR_CALLBACK_KEY, callback);
IContentProvider cp = sProviderHolder.getProvider(resolver);
- cp.call(resolver.getPackageName(), resolver.getFeatureId(),
+ cp.call(resolver.getPackageName(), resolver.getAttributionTag(),
sProviderHolder.mUri.getAuthority(),
CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG, null, arg);
} catch (RemoteException e) {
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index 72e9ad0..8f858d5 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -77,6 +77,15 @@
*/
public static final @RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST = 0x2;
+ /**
+ * Indicates the request came from a password field.
+ *
+ * (TODO: b/141703197) Temporary fix for augmented autofill showing passwords.
+ *
+ * @hide
+ */
+ public static final @RequestFlags int FLAG_PASSWORD_INPUT_TYPE = 0x4;
+
/** @hide */
public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE;
@@ -149,7 +158,8 @@
/** @hide */
@IntDef(flag = true, prefix = "FLAG_", value = {
FLAG_MANUAL_REQUEST,
- FLAG_COMPATIBILITY_MODE_REQUEST
+ FLAG_COMPATIBILITY_MODE_REQUEST,
+ FLAG_PASSWORD_INPUT_TYPE
})
@Retention(RetentionPolicy.SOURCE)
@DataClass.Generated.Member
@@ -169,6 +179,8 @@
return "FLAG_MANUAL_REQUEST";
case FLAG_COMPATIBILITY_MODE_REQUEST:
return "FLAG_COMPATIBILITY_MODE_REQUEST";
+ case FLAG_PASSWORD_INPUT_TYPE:
+ return "FLAG_PASSWORD_INPUT_TYPE";
default: return Integer.toHexString(value);
}
}
@@ -223,7 +235,8 @@
Preconditions.checkFlagsArgument(
mFlags,
FLAG_MANUAL_REQUEST
- | FLAG_COMPATIBILITY_MODE_REQUEST);
+ | FLAG_COMPATIBILITY_MODE_REQUEST
+ | FLAG_PASSWORD_INPUT_TYPE);
this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
onConstructed();
@@ -352,7 +365,8 @@
Preconditions.checkFlagsArgument(
mFlags,
FLAG_MANUAL_REQUEST
- | FLAG_COMPATIBILITY_MODE_REQUEST);
+ | FLAG_COMPATIBILITY_MODE_REQUEST
+ | FLAG_PASSWORD_INPUT_TYPE);
this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
onConstructed();
@@ -373,10 +387,10 @@
};
@DataClass.Generated(
- time = 1575928271155L,
+ time = 1583196707026L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/service/autofill/FillRequest.java",
- inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final int INVALID_REQUEST_ID\nprivate final int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
+ inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final int INVALID_REQUEST_ID\nprivate final int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/service/dataloader/DataLoaderService.java b/core/java/android/service/dataloader/DataLoaderService.java
index 0b9a8af..d4db79e 100644
--- a/core/java/android/service/dataloader/DataLoaderService.java
+++ b/core/java/android/service/dataloader/DataLoaderService.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.Service;
import android.content.Intent;
@@ -206,6 +207,7 @@
* @throws IOException if trouble opening the file for writing, such as lack of disk space
* or unavailable media.
*/
+ @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
public void writeData(@NonNull String name, long offsetBytes, long lengthBytes,
@NonNull ParcelFileDescriptor incomingFd) throws IOException {
try {
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 8e6f77b..4a0dd87 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -1314,7 +1314,8 @@
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(mContext);
int res = mSystemService.startVoiceActivity(mToken, intent,
- intent.resolveType(mContext.getContentResolver()), mContext.getFeatureId());
+ intent.resolveType(mContext.getContentResolver()),
+ mContext.getAttributionTag());
Instrumentation.checkStartActivityResult(res, intent);
} catch (RemoteException e) {
}
@@ -1342,7 +1343,8 @@
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(mContext);
int res = mSystemService.startAssistantActivity(mToken, intent,
- intent.resolveType(mContext.getContentResolver()), mContext.getFeatureId());
+ intent.resolveType(mContext.getContentResolver()),
+ mContext.getAttributionTag());
Instrumentation.checkStartActivityResult(res, intent);
} catch (RemoteException e) {
}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index bf3c088..f531e12 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -124,8 +124,6 @@
private static final int MSG_REQUEST_WALLPAPER_COLORS = 10050;
private static final int MSG_SCALE = 10100;
- private static final float MAX_SCALE = 1.15f;
-
private static final int NOTIFY_COLORS_RATE_LIMIT_MS = 1000;
private final ArrayList<Engine> mActiveEngines
@@ -351,7 +349,7 @@
@Override
public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
- boolean sync) {
+ float zoom, boolean sync) {
synchronized (mLock) {
if (DEBUG) Log.v(TAG, "Dispatch wallpaper offsets: " + x + ", " + y);
mPendingXOffset = x;
@@ -366,6 +364,8 @@
Message msg = mCaller.obtainMessage(MSG_WALLPAPER_OFFSETS);
mCaller.sendMessage(msg);
}
+ Message msg = mCaller.obtainMessageI(MSG_SCALE, Float.floatToIntBits(zoom));
+ mCaller.sendMessage(msg);
}
}
@@ -462,6 +462,18 @@
}
/**
+ * This will be called when the wallpaper is first started. If true is returned, the system
+ * will zoom in the wallpaper by default and zoom it out as the user interacts,
+ * to create depth. Otherwise, zoom will have to be handled manually
+ * in {@link #onZoomChanged(float)}.
+ *
+ * @hide
+ */
+ public boolean shouldZoomOutWallpaper() {
+ return false;
+ }
+
+ /**
* Control whether this wallpaper will receive raw touch events
* from the window manager as the user interacts with the window
* that is currently displaying the wallpaper. By default they
@@ -870,6 +882,7 @@
Log.w(TAG, "Failed to add window while updating wallpaper surface.");
return;
}
+ mSession.setShouldZoomOutWallpaper(mWindow, shouldZoomOutWallpaper());
mCreated = true;
mInputEventReceiver = new WallpaperInputEventReceiver(
@@ -964,7 +977,6 @@
c.surfaceCreated(mSurfaceHolder);
}
}
- onZoomChanged(0f);
}
redrawNeeded |= creating || (relayoutResult
@@ -1125,7 +1137,6 @@
mIsInAmbientMode = inAmbientMode;
if (mCreated) {
onAmbientModeChanged(inAmbientMode, animationDuration);
- setZoom(0);
}
}
}
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index e93ba16..92f3538 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -342,7 +342,7 @@
}
try {
mService.startListening(recognizerIntent, mListener, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
if (DBG) Log.d(TAG, "service start listening command succeded");
} catch (final RemoteException e) {
Log.e(TAG, "startListening() failed", e);
@@ -357,7 +357,7 @@
}
try {
mService.stopListening(mListener, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
if (DBG) Log.d(TAG, "service stop listening command succeded");
} catch (final RemoteException e) {
Log.e(TAG, "stopListening() failed", e);
@@ -371,7 +371,7 @@
return;
}
try {
- mService.cancel(mListener, mContext.getOpPackageName(), mContext.getFeatureId());
+ mService.cancel(mListener, mContext.getOpPackageName(), mContext.getAttributionTag());
if (DBG) Log.d(TAG, "service cancel command succeded");
} catch (final RemoteException e) {
Log.e(TAG, "cancel() failed", e);
@@ -400,7 +400,8 @@
public void destroy() {
if (mService != null) {
try {
- mService.cancel(mListener, mContext.getOpPackageName(), mContext.getFeatureId());
+ mService.cancel(mListener, mContext.getOpPackageName(),
+ mContext.getAttributionTag());
} catch (final RemoteException e) {
// Not important
}
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 7238b12..ab9df56 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -116,7 +116,7 @@
mSubscriptionChangedListenerMap.put(listener, callback);
try {
sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(),
- mContext.getFeatureId(), callback);
+ mContext.getAttributionTag(), callback);
} catch (RemoteException ex) {
// system server crash
}
@@ -175,7 +175,7 @@
mOpportunisticSubscriptionChangedListenerMap.put(listener, callback);
try {
sRegistry.addOnOpportunisticSubscriptionsChangedListener(mContext.getOpPackageName(),
- mContext.getFeatureId(), callback);
+ mContext.getAttributionTag(), callback);
} catch (RemoteException ex) {
// system server crash
}
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index 2aca36a..82c7ea7 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.telephony.PhoneNumberUtils;
@@ -663,9 +664,11 @@
private static void gatherTelLinks(ArrayList<LinkSpec> links, Spannable s,
@Nullable Context context) {
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
+ final Context ctx = (context != null) ? context : ActivityThread.currentApplication();
+ final String regionCode = (ctx != null) ? ctx.getSystemService(TelephonyManager.class).
+ getSimCountryIso().toUpperCase(Locale.US) : Locale.getDefault().getCountry();
Iterable<PhoneNumberMatch> matches = phoneUtil.findNumbers(s.toString(),
- TelephonyManager.getDefaultSimCountryIso().toUpperCase(Locale.US),
- Leniency.POSSIBLE, Long.MAX_VALUE);
+ regionCode, Leniency.POSSIBLE, Long.MAX_VALUE);
for (PhoneNumberMatch match : matches) {
LinkSpec spec = new LinkSpec();
spec.url = "tel:" + PhoneNumberUtils.normalizeNumber(match.rawString());
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 3927ebf..9f2d36d 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -102,9 +102,9 @@
void closeSystemDialogs(String reason);
/**
- * Called for wallpaper windows when their offsets change.
+ * Called for wallpaper windows when their offsets or zoom level change.
*/
- void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, boolean sync);
+ void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, float zoom, boolean sync);
void dispatchWallpaperCommand(String action, int x, int y,
int z, in Bundle extras, boolean sync);
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 91000a9..dfe89a3 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -221,6 +221,19 @@
*/
void setWallpaperPosition(IBinder windowToken, float x, float y, float xstep, float ystep);
+ /**
+ * For wallpaper windows, sets the scale of the wallpaper based on
+ * SystemUI behavior.
+ */
+ void setWallpaperZoomOut(IBinder windowToken, float scale);
+
+ /**
+ * For wallpaper windows, sets whether the wallpaper should actually be
+ * scaled when setWallpaperZoomOut is called. If set to false, the WallpaperService will
+ * receive the zoom out value but the surface won't be scaled.
+ */
+ void setShouldZoomOutWallpaper(IBinder windowToken, boolean shouldZoom);
+
@UnsupportedAppUsage
void wallpaperOffsetsComplete(IBinder window);
diff --git a/core/java/android/view/InsetsAnimationControlCallbacks.java b/core/java/android/view/InsetsAnimationControlCallbacks.java
index 5d5edec..a15d6c7 100644
--- a/core/java/android/view/InsetsAnimationControlCallbacks.java
+++ b/core/java/android/view/InsetsAnimationControlCallbacks.java
@@ -16,7 +16,6 @@
package android.view;
-import android.view.InsetsController.LayoutInsetsDuringAnimation;
import android.view.WindowInsetsAnimation.Bounds;
/**
@@ -37,7 +36,7 @@
void startAnimation(InsetsAnimationControlImpl controller,
WindowInsetsAnimationControlListener listener, int types,
WindowInsetsAnimation animation,
- Bounds bounds, @LayoutInsetsDuringAnimation int layoutDuringAnimation);
+ Bounds bounds);
/**
* Schedule the apply by posting the animation callback.
@@ -46,10 +45,10 @@
/**
* Finish the final steps after the animation.
- * @param controller The controller used to control the animation.
+ * @param runner The runner used to run the animation.
* @param shown {@code true} if the insets are shown.
*/
- void notifyFinished(InsetsAnimationControlImpl controller, boolean shown);
+ void notifyFinished(InsetsAnimationControlRunner runner, boolean shown);
/**
* Apply the new params to the surface.
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index ae509f3..2b30c2d 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -31,9 +31,7 @@
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.SparseSetArray;
-import android.view.InsetsController.LayoutInsetsDuringAnimation;
import android.view.InsetsState.InternalInsetsSide;
-import android.view.InsetsState.InternalInsetsType;
import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsAnimation.Bounds;
@@ -49,7 +47,8 @@
* @hide
*/
@VisibleForTesting
-public class InsetsAnimationControlImpl implements WindowInsetsAnimationController {
+public class InsetsAnimationControlImpl implements WindowInsetsAnimationController,
+ InsetsAnimationControlRunner {
private final Rect mTmpFrame = new Rect();
@@ -84,8 +83,7 @@
InsetsState state, WindowInsetsAnimationControlListener listener,
@InsetsType int types,
InsetsAnimationControlCallbacks controller, long durationMs, Interpolator interpolator,
- boolean fade, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation,
- @AnimationType int animationType) {
+ boolean fade, @AnimationType int animationType) {
mControls = controls;
mListener = listener;
mTypes = types;
@@ -105,7 +103,7 @@
mAnimation.setAlpha(getCurrentAlpha());
mAnimationType = animationType;
mController.startAnimation(this, listener, types, mAnimation,
- new Bounds(mHiddenInsets, mShownInsets), layoutInsetsDuringAnimation);
+ new Bounds(mHiddenInsets, mShownInsets));
}
@Override
@@ -133,11 +131,8 @@
return mTypes;
}
- boolean controlsInternalType(@InternalInsetsType int type) {
- return InsetsState.toInternalType(mTypes).contains(type);
- }
-
- @AnimationType int getAnimationType() {
+ @Override
+ public @AnimationType int getAnimationType() {
return mAnimationType;
}
@@ -205,7 +200,8 @@
return mAnimation.getFraction();
}
- public void onCancelled() {
+ @Override
+ public void cancel() {
if (mFinished) {
return;
}
@@ -217,7 +213,8 @@
return mCancelled;
}
- WindowInsetsAnimation getAnimation() {
+ @Override
+ public WindowInsetsAnimation getAnimation() {
return mAnimation;
}
@@ -225,6 +222,10 @@
return mListener;
}
+ SparseArray<InsetsSourceControl> getControls() {
+ return mControls;
+ }
+
private Insets calculateInsets(InsetsState state, Rect frame,
SparseArray<InsetsSourceControl> controls, boolean shown,
@Nullable @InternalInsetsSide SparseIntArray typeSideMap) {
diff --git a/core/java/android/view/InsetsAnimationControlRunner.java b/core/java/android/view/InsetsAnimationControlRunner.java
new file mode 100644
index 0000000..0711c3e
--- /dev/null
+++ b/core/java/android/view/InsetsAnimationControlRunner.java
@@ -0,0 +1,56 @@
+/*
+ * 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.view;
+
+import android.view.InsetsController.AnimationType;
+import android.view.InsetsState.InternalInsetsType;
+import android.view.WindowInsets.Type.InsetsType;
+
+/**
+ * Interface representing a runner for an insets animation.
+ *
+ * @hide
+ */
+public interface InsetsAnimationControlRunner {
+
+ /**
+ * @return The {@link InsetsType} the animation of this runner is controlling.
+ */
+ @InsetsType int getTypes();
+
+ /**
+ * Cancels the animation.
+ */
+ void cancel();
+
+ /**
+ * @return The animation this runner is running.
+ */
+ WindowInsetsAnimation getAnimation();
+
+ /**
+ * @return Whether {@link #getTypes()} maps to a specific {@link InternalInsetsType}.
+ */
+ default boolean controlsInternalType(@InternalInsetsType int type) {
+ return InsetsState.toInternalType(getTypes()).contains(type);
+ }
+
+ /**
+ * @return The animation type this runner is running.
+ */
+ @AnimationType int getAnimationType();
+}
diff --git a/core/java/android/view/InsetsAnimationThread.java b/core/java/android/view/InsetsAnimationThread.java
new file mode 100644
index 0000000..cdf9733
--- /dev/null
+++ b/core/java/android/view/InsetsAnimationThread.java
@@ -0,0 +1,70 @@
+/*
+ * 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.view;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Trace;
+
+/**
+ * Thread to be used for inset animations to be running off the main thread.
+ * @hide
+ */
+public class InsetsAnimationThread extends HandlerThread {
+
+ private static InsetsAnimationThread sInstance;
+ private static Handler sHandler;
+
+ private InsetsAnimationThread() {
+ // TODO: Should this use higher priority?
+ super("InsetsAnimations");
+ }
+
+ private static void ensureThreadLocked() {
+ if (sInstance == null) {
+ sInstance = new InsetsAnimationThread();
+ sInstance.start();
+ sInstance.getLooper().setTraceTag(Trace.TRACE_TAG_VIEW);
+ sHandler = new Handler(sInstance.getLooper());
+ }
+ }
+
+ public static void release() {
+ synchronized (InsetsAnimationThread.class) {
+ if (sInstance == null) {
+ return;
+ }
+ sInstance.getLooper().quitSafely();
+ sInstance = null;
+ sHandler = null;
+ }
+ }
+
+ public static InsetsAnimationThread get() {
+ synchronized (InsetsAnimationThread.class) {
+ ensureThreadLocked();
+ return sInstance;
+ }
+ }
+
+ public static Handler getHandler() {
+ synchronized (InsetsAnimationThread.class) {
+ ensureThreadLocked();
+ return sHandler;
+ }
+ }
+}
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
new file mode 100644
index 0000000..9c27802
--- /dev/null
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -0,0 +1,130 @@
+/*
+ * 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.view;
+
+import static android.view.SyncRtSurfaceTransactionApplier.applyParams;
+
+import android.annotation.UiThread;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.util.SparseArray;
+import android.view.InsetsController.AnimationType;
+import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
+import android.view.WindowInsets.Type.InsetsType;
+import android.view.WindowInsetsAnimation.Bounds;
+import android.view.animation.Interpolator;
+
+/**
+ * Insets animation runner that uses {@link InsetsAnimationThread} to run the animation off from the
+ * main thread.
+ *
+ * @hide
+ */
+public class InsetsAnimationThreadControlRunner implements InsetsAnimationControlRunner {
+
+ private final InsetsAnimationControlImpl mControl;
+ private final InsetsAnimationControlCallbacks mOuterCallbacks;
+ private final Handler mMainThreadHandler;
+ private final InsetsState mState = new InsetsState();
+ private final InsetsAnimationControlCallbacks mCallbacks =
+ new InsetsAnimationControlCallbacks() {
+
+ private final float[] mTmpFloat9 = new float[9];
+
+ @Override
+ @UiThread
+ public void startAnimation(InsetsAnimationControlImpl controller,
+ WindowInsetsAnimationControlListener listener, int types,
+ WindowInsetsAnimation animation, Bounds bounds) {
+ // Animation will be started in constructor already.
+ }
+
+ @Override
+ public void scheduleApplyChangeInsets() {
+ mControl.applyChangeInsets(mState);
+ }
+
+ @Override
+ public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) {
+ releaseControls(mControl.getControls());
+ mMainThreadHandler.post(() ->
+ mOuterCallbacks.notifyFinished(InsetsAnimationThreadControlRunner.this, shown));
+ }
+
+ @Override
+ public void applySurfaceParams(SurfaceParams... params) {
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ for (int i = params.length - 1; i >= 0; i--) {
+ SyncRtSurfaceTransactionApplier.SurfaceParams surfaceParams = params[i];
+ applyParams(t, surfaceParams, mTmpFloat9);
+ }
+ t.apply();
+ t.close();
+ }
+ };
+
+ @UiThread
+ public InsetsAnimationThreadControlRunner(SparseArray<InsetsSourceControl> controls, Rect frame,
+ InsetsState state, WindowInsetsAnimationControlListener listener,
+ @InsetsType int types,
+ InsetsAnimationControlCallbacks controller, long durationMs, Interpolator interpolator,
+ boolean fade, @AnimationType int animationType, Handler mainThreadHandler) {
+ mMainThreadHandler = mainThreadHandler;
+ mOuterCallbacks = controller;
+ mControl = new InsetsAnimationControlImpl(copyControls(controls), frame, state, listener,
+ types, mCallbacks, durationMs, interpolator, fade, animationType);
+ InsetsAnimationThread.getHandler().post(() -> listener.onReady(mControl, types));
+ }
+
+ private void releaseControls(SparseArray<InsetsSourceControl> controls) {
+ for (int i = controls.size() - 1; i >= 0; i--) {
+ controls.valueAt(i).release(SurfaceControl::release);
+ }
+ }
+
+ private SparseArray<InsetsSourceControl> copyControls(
+ SparseArray<InsetsSourceControl> controls) {
+ SparseArray<InsetsSourceControl> copy = new SparseArray<>(controls.size());
+ for (int i = 0; i < controls.size(); i++) {
+ copy.append(controls.keyAt(i), new InsetsSourceControl(controls.valueAt(i)));
+ }
+ return copy;
+ }
+
+ @Override
+ @UiThread
+ public int getTypes() {
+ return mControl.getTypes();
+ }
+
+ @Override
+ @UiThread
+ public void cancel() {
+ InsetsAnimationThread.getHandler().post(mControl::cancel);
+ }
+
+ @Override
+ @UiThread
+ public WindowInsetsAnimation getAnimation() {
+ return mControl.getAnimation();
+ }
+
+ @Override
+ public int getAnimationType() {
+ return mControl.getAnimationType();
+ }
+}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 607886f..c1763d6 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -23,6 +23,7 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CONTROLLED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
+import android.animation.AnimationHandler;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
@@ -53,6 +54,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -167,10 +169,22 @@
private WindowInsetsAnimationController mController;
private ObjectAnimator mAnimator;
- protected boolean mShow;
+ private final boolean mShow;
+ private final boolean mUseSfVsync;
- public InternalAnimationControlListener(boolean show) {
+ private ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
+ new ThreadLocal<AnimationHandler>() {
+ @Override
+ protected AnimationHandler initialValue() {
+ AnimationHandler handler = new AnimationHandler();
+ handler.setProvider(new SfVsyncFrameCallbackProvider());
+ return handler;
+ }
+ };
+
+ public InternalAnimationControlListener(boolean show, boolean useSfVsync) {
mShow = show;
+ mUseSfVsync = useSfVsync;
}
@Override
@@ -193,6 +207,9 @@
onAnimationFinish();
}
});
+ if (mUseSfVsync) {
+ mAnimator.setAnimationHandler(mSfAnimationHandlerThreadLocal.get());
+ }
mAnimator.start();
}
@@ -228,12 +245,12 @@
*/
private static class RunningAnimation {
- RunningAnimation(InsetsAnimationControlImpl control, int type) {
- this.control = control;
+ RunningAnimation(InsetsAnimationControlRunner runner, int type) {
+ this.runner = runner;
this.type = type;
}
- final InsetsAnimationControlImpl control;
+ final InsetsAnimationControlRunner runner;
final @AnimationType int type;
/**
@@ -252,7 +269,7 @@
PendingControlRequest(@InsetsType int types, WindowInsetsAnimationControlListener listener,
long durationMs, Interpolator interpolator, @AnimationType int animationType,
@LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation,
- CancellationSignal cancellationSignal) {
+ CancellationSignal cancellationSignal, boolean useInsetsAnimationThread) {
this.types = types;
this.listener = listener;
this.durationMs = durationMs;
@@ -260,6 +277,7 @@
this.animationType = animationType;
this.layoutInsetsDuringAnimation = layoutInsetsDuringAnimation;
this.cancellationSignal = cancellationSignal;
+ this.useInsetsAnimationThread = useInsetsAnimationThread;
}
final @InsetsType int types;
@@ -269,6 +287,7 @@
final @AnimationType int animationType;
final @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation;
final CancellationSignal cancellationSignal;
+ final boolean useInsetsAnimationThread;
}
private final String TAG = "InsetsControllerImpl";
@@ -347,15 +366,20 @@
InsetsState state = new InsetsState(mState, true /* copySources */);
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
RunningAnimation runningAnimation = mRunningAnimations.get(i);
- InsetsAnimationControlImpl control = runningAnimation.control;
+ InsetsAnimationControlRunner runner = runningAnimation.runner;
+ if (runner instanceof InsetsAnimationControlImpl) {
+ InsetsAnimationControlImpl control = (InsetsAnimationControlImpl) runner;
- // Keep track of running animation to be dispatched. Aggregate it here such that if
- // it gets finished within applyChangeInsets we still dispatch it to onProgress.
- if (runningAnimation.startDispatched) {
- mTmpRunningAnims.add(control.getAnimation());
- }
- if (control.applyChangeInsets(state)) {
- mTmpFinishedControls.add(control);
+ // Keep track of running animation to be dispatched. Aggregate it here such that
+ // if it gets finished within applyChangeInsets we still dispatch it to
+ // onProgress.
+ if (runningAnimation.startDispatched) {
+ mTmpRunningAnims.add(control.getAnimation());
+ }
+
+ if (control.applyChangeInsets(state)) {
+ mTmpFinishedControls.add(control);
+ }
}
}
@@ -499,7 +523,8 @@
pendingRequest.listener, mFrame,
true /* fromIme */, pendingRequest.durationMs, pendingRequest.interpolator,
false /* fade */, pendingRequest.animationType,
- pendingRequest.layoutInsetsDuringAnimation);
+ pendingRequest.layoutInsetsDuringAnimation,
+ pendingRequest.useInsetsAnimationThread);
pendingRequest.cancellationSignal.setOnCancelListener(cancellationSignal::cancel);
return;
}
@@ -563,7 +588,8 @@
return cancellationSignal;
}
return controlAnimationUnchecked(types, listener, mFrame, fromIme, durationMs, interpolator,
- false /* fade */, animationType, getLayoutInsetsDuringAnimationMode(types));
+ false /* fade */, animationType, getLayoutInsetsDuringAnimationMode(types),
+ false /* useInsetsAnimationThread */);
}
private boolean checkDisplayFramesForControlling() {
@@ -577,7 +603,8 @@
WindowInsetsAnimationControlListener listener, Rect frame, boolean fromIme,
long durationMs, Interpolator interpolator, boolean fade,
@AnimationType int animationType,
- @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
+ @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation,
+ boolean useInsetsAnimationThread) {
CancellationSignal cancellationSignal = new CancellationSignal();
if (types == 0) {
// nothing to animate.
@@ -600,7 +627,8 @@
abortPendingImeControlRequest();
final PendingControlRequest request = new PendingControlRequest(types,
listener, durationMs,
- interpolator, animationType, layoutInsetsDuringAnimation, cancellationSignal);
+ interpolator, animationType, layoutInsetsDuringAnimation, cancellationSignal,
+ useInsetsAnimationThread);
mPendingImeControlRequest = request;
mHandler.postDelayed(mPendingControlTimeout, PENDING_CONTROL_TIMEOUT_MS);
cancellationSignal.setOnCancelListener(() -> {
@@ -617,11 +645,21 @@
return cancellationSignal;
}
- final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(controls,
- frame, mState, listener, typesReady, this, durationMs, interpolator, fade,
- layoutInsetsDuringAnimation, animationType);
- mRunningAnimations.add(new RunningAnimation(controller, animationType));
- cancellationSignal.setOnCancelListener(controller::onCancelled);
+
+ final InsetsAnimationControlRunner runner = useInsetsAnimationThread
+ ? new InsetsAnimationThreadControlRunner(controls,
+ frame, mState, listener, typesReady, this, durationMs, interpolator, fade,
+ animationType, mViewRoot.mHandler)
+ : new InsetsAnimationControlImpl(controls,
+ frame, mState, listener, typesReady, this, durationMs, interpolator, fade,
+ animationType);
+ mRunningAnimations.add(new RunningAnimation(runner, animationType));
+ cancellationSignal.setOnCancelListener(runner::cancel);
+ if (layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN) {
+ showDirectly(types);
+ } else {
+ hideDirectly(types, false /* animationFinished */, animationType);
+ }
return cancellationSignal;
}
@@ -705,7 +743,7 @@
private void cancelExistingControllers(@InsetsType int types) {
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
- InsetsAnimationControlImpl control = mRunningAnimations.get(i).control;
+ InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
if ((control.getTypes() & types) != 0) {
cancelAnimation(control, true /* invokeCallback */);
}
@@ -725,13 +763,13 @@
@VisibleForTesting
@Override
- public void notifyFinished(InsetsAnimationControlImpl controller, boolean shown) {
- cancelAnimation(controller, false /* invokeCallback */);
+ public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) {
+ cancelAnimation(runner, false /* invokeCallback */);
if (shown) {
- showDirectly(controller.getTypes());
+ showDirectly(runner.getTypes());
} else {
- hideDirectly(controller.getTypes(), true /* animationFinished */,
- controller.getAnimationType());
+ hideDirectly(runner.getTypes(), true /* animationFinished */,
+ runner.getAnimationType());
}
}
@@ -756,7 +794,7 @@
void notifyControlRevoked(InsetsSourceConsumer consumer) {
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
- InsetsAnimationControlImpl control = mRunningAnimations.get(i).control;
+ InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
if ((control.getTypes() & toPublicType(consumer.getType())) != 0) {
cancelAnimation(control, true /* invokeCallback */);
}
@@ -766,12 +804,12 @@
}
}
- private void cancelAnimation(InsetsAnimationControlImpl control, boolean invokeCallback) {
+ private void cancelAnimation(InsetsAnimationControlRunner control, boolean invokeCallback) {
if (invokeCallback) {
- control.onCancelled();
+ control.cancel();
}
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
- if (mRunningAnimations.get(i).control == control) {
+ if (mRunningAnimations.get(i).runner == control) {
mRunningAnimations.remove(i);
break;
}
@@ -844,7 +882,7 @@
@VisibleForTesting
public @AnimationType int getAnimationType(@InternalInsetsType int type) {
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
- InsetsAnimationControlImpl control = mRunningAnimations.get(i).control;
+ InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
if (control.controlsInternalType(type)) {
return mRunningAnimations.get(i).type;
}
@@ -878,15 +916,24 @@
return;
}
+ boolean useInsetsAnimationThread = canUseInsetsAnimationThread();
final InternalAnimationControlListener listener =
- new InternalAnimationControlListener(show);
+ new InternalAnimationControlListener(show, useInsetsAnimationThread);
// Show/hide animations always need to be relative to the display frame, in order that shown
// and hidden state insets are correct.
controlAnimationUnchecked(
types, listener, mState.getDisplayFrame(), fromIme, listener.getDurationMs(),
INTERPOLATOR, true /* fade */, show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE,
show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN
- : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN);
+ : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN,
+ useInsetsAnimationThread);
+ }
+
+ private boolean canUseInsetsAnimationThread() {
+ if (mViewRoot.mView == null) {
+ return true;
+ }
+ return !mViewRoot.mView.hasWindowInsetsAnimationCallback();
}
private void hideDirectly(
@@ -921,13 +968,7 @@
@Override
public void startAnimation(InsetsAnimationControlImpl controller,
WindowInsetsAnimationControlListener listener, int types,
- WindowInsetsAnimation animation, Bounds bounds, int layoutDuringAnimation) {
- if (layoutDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN) {
- showDirectly(types);
- } else {
- hideDirectly(types, false /* animationFinished */, controller.getAnimationType());
- }
-
+ WindowInsetsAnimation animation, Bounds bounds) {
if (mViewRoot.mView == null) {
return;
}
@@ -941,7 +982,7 @@
}
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
RunningAnimation runningAnimation = mRunningAnimations.get(i);
- if (runningAnimation.control == controller) {
+ if (runningAnimation.runner == controller) {
runningAnimation.startDispatched = true;
}
}
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index 252fc0c..3325734 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -117,7 +117,7 @@
}
}
if (lastControl != null) {
- lastControl.release(mController);
+ lastControl.release(mController::releaseSurfaceControlFromRt);
}
}
diff --git a/core/java/android/view/InsetsSourceControl.java b/core/java/android/view/InsetsSourceControl.java
index 75f6eab..f3ec65f 100644
--- a/core/java/android/view/InsetsSourceControl.java
+++ b/core/java/android/view/InsetsSourceControl.java
@@ -22,6 +22,8 @@
import android.os.Parcelable;
import android.view.InsetsState.InternalInsetsType;
+import java.util.function.Consumer;
+
/**
* Represents a parcelable object to allow controlling a single {@link InsetsSource}.
* @hide
@@ -94,9 +96,9 @@
dest.writeParcelable(mSurfacePosition, 0 /* flags*/);
}
- public void release(InsetsController controller) {
+ public void release(Consumer<SurfaceControl> surfaceReleaseConsumer) {
if (mLeash != null) {
- controller.releaseSurfaceControlFromRt(mLeash);
+ surfaceReleaseConsumer.accept(mLeash);
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6236e6e..879f284 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -11227,6 +11227,15 @@
}
/**
+ * @return {@code true} if any {@link WindowInsetsAnimation.Callback} is registered on the view
+ * or view tree of the sub-hierarchy {@code false} otherwise.
+ * @hide
+ */
+ public boolean hasWindowInsetsAnimationCallback() {
+ return getListenerInfo().mWindowInsetsAnimationCallback != null;
+ }
+
+ /**
* Dispatches {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)}
* when Window Insets animation is being prepared.
* @param animation current animation
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7d4ec3d..e34e84c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -7258,6 +7258,34 @@
: DISPATCH_MODE_CONTINUE_ON_SUBTREE;
}
+ /**
+ * @hide
+ */
+ @Override
+ public boolean hasWindowInsetsAnimationCallback() {
+ if (super.hasWindowInsetsAnimationCallback()) {
+ return true;
+ }
+
+ // If we are root-level content view that fits insets, we imitate consuming behavior, so
+ // no child will retrieve window insets animation callback.
+ // See dispatchWindowInsetsAnimationPrepare.
+ boolean isOptionalFitSystemWindows = (mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) != 0
+ || isFrameworkOptionalFitsSystemWindows();
+ if (isOptionalFitSystemWindows && mAttachInfo != null
+ && mAttachInfo.mContentOnApplyWindowInsetsListener != null) {
+ return false;
+ }
+
+ final int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ if (getChildAt(i).hasWindowInsetsAnimationCallback()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public void dispatchWindowInsetsAnimationPrepare(
@NonNull WindowInsetsAnimation animation) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9e5298b..26ac4fc 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -9054,7 +9054,7 @@
@Override
public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
- boolean sync) {
+ float zoom, boolean sync) {
if (sync) {
try {
mWindowSession.wallpaperOffsetsComplete(asBinder());
diff --git a/core/java/android/view/WindowContainerTransaction.java b/core/java/android/view/WindowContainerTransaction.java
index e05c374..9c16e13 100644
--- a/core/java/android/view/WindowContainerTransaction.java
+++ b/core/java/android/view/WindowContainerTransaction.java
@@ -131,6 +131,31 @@
}
/**
+ * Set the windowing mode of children of a given root task, without changing
+ * the windowing mode of the Task itself. This can be used during transitions
+ * for example to make the activity render it's fullscreen configuration
+ * while the Task is still in PIP, so you can complete the animation.
+ *
+ * TODO(b/134365562): Can be removed once TaskOrg drives full-screen
+ */
+ public WindowContainerTransaction setActivityWindowingMode(IWindowContainer container,
+ int windowingMode) {
+ Change chg = getOrCreateChange(container.asBinder());
+ chg.mActivityWindowingMode = windowingMode;
+ return this;
+ }
+
+ /**
+ * Sets the windowing mode of the given container.
+ */
+ public WindowContainerTransaction setWindowingMode(IWindowContainer container,
+ int windowingMode) {
+ Change chg = getOrCreateChange(container.asBinder());
+ chg.mWindowingMode = windowingMode;
+ return this;
+ }
+
+ /**
* Sets whether a container or any of its children can be focusable. When {@code false}, no
* child can be focused; however, when {@code true}, it is still possible for children to be
* non-focusable due to WM policy.
@@ -235,6 +260,9 @@
private Rect mPinnedBounds = null;
private SurfaceControl.Transaction mBoundsChangeTransaction = null;
+ private int mActivityWindowingMode = -1;
+ private int mWindowingMode = -1;
+
public Change() {}
protected Change(Parcel in) {
@@ -251,6 +279,17 @@
mBoundsChangeTransaction =
SurfaceControl.Transaction.CREATOR.createFromParcel(in);
}
+
+ mWindowingMode = in.readInt();
+ mActivityWindowingMode = in.readInt();
+ }
+
+ public int getWindowingMode() {
+ return mWindowingMode;
+ }
+
+ public int getActivityWindowingMode() {
+ return mActivityWindowingMode;
}
public Configuration getConfiguration() {
@@ -340,6 +379,9 @@
if (mBoundsChangeTransaction != null) {
mBoundsChangeTransaction.writeToParcel(dest, flags);
}
+
+ dest.writeInt(mWindowingMode);
+ dest.writeInt(mActivityWindowingMode);
}
@Override
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 867b648..c5fa3c8 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -805,6 +805,7 @@
@ViewDebug.IntToString(from = TYPE_APPLICATION_OVERLAY,
to = "APPLICATION_OVERLAY")
})
+ @WindowType
public int type;
/**
@@ -1244,13 +1245,47 @@
public static final int INVALID_WINDOW_TYPE = -1;
/**
+ * @hide
+ */
+ @IntDef(prefix = "TYPE_", value = {
+ TYPE_ACCESSIBILITY_OVERLAY,
+ TYPE_APPLICATION,
+ TYPE_APPLICATION_ATTACHED_DIALOG,
+ TYPE_APPLICATION_MEDIA,
+ TYPE_APPLICATION_OVERLAY,
+ TYPE_APPLICATION_PANEL,
+ TYPE_APPLICATION_STARTING,
+ TYPE_APPLICATION_SUB_PANEL,
+ TYPE_BASE_APPLICATION,
+ TYPE_DRAWN_APPLICATION,
+ TYPE_INPUT_METHOD,
+ TYPE_INPUT_METHOD_DIALOG,
+ TYPE_KEYGUARD,
+ TYPE_KEYGUARD_DIALOG,
+ TYPE_PHONE,
+ TYPE_PRIORITY_PHONE,
+ TYPE_PRIVATE_PRESENTATION,
+ TYPE_SEARCH_BAR,
+ TYPE_STATUS_BAR,
+ TYPE_STATUS_BAR_PANEL,
+ TYPE_SYSTEM_ALERT,
+ TYPE_SYSTEM_DIALOG,
+ TYPE_SYSTEM_ERROR,
+ TYPE_SYSTEM_OVERLAY,
+ TYPE_TOAST,
+ TYPE_WALLPAPER,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface WindowType {}
+
+ /**
* Return true if the window type is an alert window.
*
* @param type The window type.
* @return If the window type is an alert window.
* @hide
*/
- public static boolean isSystemAlertWindowType(int type) {
+ public static boolean isSystemAlertWindowType(@WindowType int type) {
switch (type) {
case TYPE_PHONE:
case TYPE_PRIORITY_PHONE:
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 01a1c77..410d9af 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -504,6 +504,7 @@
}
void doRemoveView(ViewRootImpl root) {
+ boolean allViewsRemoved;
synchronized (mLock) {
final int index = mRoots.indexOf(root);
if (index >= 0) {
@@ -512,10 +513,17 @@
final View view = mViews.remove(index);
mDyingViews.remove(view);
}
+ allViewsRemoved = mRoots.isEmpty();
}
if (ThreadedRenderer.sTrimForeground && ThreadedRenderer.isAvailable()) {
doTrimForeground();
}
+
+ // If we don't have any views anymore in our process, we no longer need the
+ // InsetsAnimationThread to save some resources.
+ if (allViewsRemoved) {
+ InsetsAnimationThread.release();
+ }
}
private int findViewLocked(View view, boolean required) {
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 87dcba0..144f8e3 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -312,6 +312,14 @@
}
@Override
+ public void setWallpaperZoomOut(android.os.IBinder windowToken, float zoom) {
+ }
+
+ @Override
+ public void setShouldZoomOutWallpaper(android.os.IBinder windowToken, boolean shouldZoom) {
+ }
+
+ @Override
public void wallpaperOffsetsComplete(android.os.IBinder window) {
}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index ce7cfa7..dda4e8b 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -17,6 +17,7 @@
package android.view.autofill;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
+import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE;
import static android.view.autofill.Helper.sDebug;
import static android.view.autofill.Helper.sVerbose;
import static android.view.autofill.Helper.toList;
@@ -63,6 +64,7 @@
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.accessibility.AccessibilityWindowInfo;
import android.widget.EditText;
+import android.widget.TextView;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
@@ -983,6 +985,10 @@
if (!isClientDisablingEnterExitEvent()) {
final AutofillValue value = view.getAutofillValue();
+ if (view instanceof TextView && ((TextView) view).isAnyPasswordInputType()) {
+ flags |= FLAG_PASSWORD_INPUT_TYPE;
+ }
+
if (!isActiveLocked()) {
// Starts new session.
startSessionLocked(id, null, value, flags);
@@ -1149,6 +1155,10 @@
} else {
// don't notify entered when Activity is already in background
if (!isClientDisablingEnterExitEvent()) {
+ if (view instanceof TextView && ((TextView) view).isAnyPasswordInputType()) {
+ flags |= FLAG_PASSWORD_INPUT_TYPE;
+ }
+
if (!isActiveLocked()) {
// Starts new session.
startSessionLocked(id, bounds, null, flags);
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
index e50da40..8e8c7df 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
@@ -44,15 +44,15 @@
public static final int SUGGESTION_COUNT_UNLIMITED = Integer.MAX_VALUE;
/**
- * Max number of suggestions expected from the response. Defaults to {@code
- * SUGGESTION_COUNT_UNLIMITED} if not set.
+ * Max number of suggestions expected from the response. It must be a positive value.
+ * Defaults to {@code SUGGESTION_COUNT_UNLIMITED} if not set.
*/
private final int mMaxSuggestionCount;
/**
* The {@link InlinePresentationSpec} for each suggestion in the response. If the max suggestion
* count is larger than the number of specs in the list, then the last spec is used for the
- * remainder of the suggestions.
+ * remainder of the suggestions. The list should not be empty.
*/
private final @NonNull List<InlinePresentationSpec> mPresentationSpecs;
@@ -72,6 +72,7 @@
/**
* The extras state propagated from the IME to pass extra data.
*/
+ @DataClass.MaySetToNull
private @Nullable Bundle mExtras;
/**
@@ -80,6 +81,7 @@
*
* @hide
*/
+ @DataClass.MaySetToNull
private @Nullable IBinder mHostInputToken;
/**
@@ -117,6 +119,7 @@
}
private void onConstructed() {
+ Preconditions.checkState(!mPresentationSpecs.isEmpty());
Preconditions.checkState(mMaxSuggestionCount >= mPresentationSpecs.size());
}
@@ -162,7 +165,7 @@
- // Code below generated by codegen v1.0.14.
+ // Code below generated by codegen v1.0.15.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -202,8 +205,8 @@
}
/**
- * Max number of suggestions expected from the response. Defaults to {@code
- * SUGGESTION_COUNT_UNLIMITED} if not set.
+ * Max number of suggestions expected from the response. It must be a positive value.
+ * Defaults to {@code SUGGESTION_COUNT_UNLIMITED} if not set.
*/
@DataClass.Generated.Member
public int getMaxSuggestionCount() {
@@ -213,7 +216,7 @@
/**
* The {@link InlinePresentationSpec} for each suggestion in the response. If the max suggestion
* count is larger than the number of specs in the list, then the last spec is used for the
- * remainder of the suggestions.
+ * remainder of the suggestions. The list should not be empty.
*/
@DataClass.Generated.Member
public @NonNull List<InlinePresentationSpec> getPresentationSpecs() {
@@ -419,7 +422,7 @@
* @param presentationSpecs
* The {@link InlinePresentationSpec} for each suggestion in the response. If the max suggestion
* count is larger than the number of specs in the list, then the last spec is used for the
- * remainder of the suggestions.
+ * remainder of the suggestions. The list should not be empty.
*/
public Builder(
@NonNull List<InlinePresentationSpec> presentationSpecs) {
@@ -429,8 +432,8 @@
}
/**
- * Max number of suggestions expected from the response. Defaults to {@code
- * SUGGESTION_COUNT_UNLIMITED} if not set.
+ * Max number of suggestions expected from the response. It must be a positive value.
+ * Defaults to {@code SUGGESTION_COUNT_UNLIMITED} if not set.
*/
@DataClass.Generated.Member
public @NonNull Builder setMaxSuggestionCount(int value) {
@@ -443,7 +446,7 @@
/**
* The {@link InlinePresentationSpec} for each suggestion in the response. If the max suggestion
* count is larger than the number of specs in the list, then the last spec is used for the
- * remainder of the suggestions.
+ * remainder of the suggestions. The list should not be empty.
*/
@DataClass.Generated.Member
@Override
@@ -575,10 +578,10 @@
}
@DataClass.Generated(
- time = 1582339908980L,
- codegenVersion = "1.0.14",
+ time = 1583975428858L,
+ codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java",
- inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.view.inline.InlinePresentationSpec> mPresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.Nullable android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate int mHostDisplayId\npublic void setHostInputToken(android.os.IBinder)\nprivate void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic void setHostDisplayId(int)\nprivate void onConstructed()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nprivate static android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.Nullable android.os.Bundle defaultExtras()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setPresentationSpecs(java.util.List<android.view.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.view.inline.InlinePresentationSpec> mPresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @com.android.internal.util.DataClass.MaySetToNull @android.annotation.Nullable android.os.Bundle mExtras\nprivate @com.android.internal.util.DataClass.MaySetToNull @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate int mHostDisplayId\npublic void setHostInputToken(android.os.IBinder)\nprivate void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic void setHostDisplayId(int)\nprivate void onConstructed()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nprivate static android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.Nullable android.os.Bundle defaultExtras()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setPresentationSpecs(java.util.List<android.view.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index d165bd0..ffdb89d 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -261,7 +261,7 @@
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
- String tz = intent.getStringExtra("time-zone");
+ String tz = intent.getStringExtra(Intent.EXTRA_TIMEZONE);
mClock = Clock.system(ZoneId.of(tz));
}
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index 8565493..6432438 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -173,7 +173,7 @@
return; // Test disabled the clock ticks
}
if (mTimeZone == null && Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
- final String timeZone = intent.getStringExtra("time-zone");
+ final String timeZone = intent.getStringExtra(Intent.EXTRA_TIMEZONE);
createTime(timeZone);
} else if (!mShouldRunTicker && (Intent.ACTION_TIME_TICK.equals(intent.getAction())
|| Intent.ACTION_TIME_CHANGED.equals(intent.getAction()))) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 0d82065..2168018 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6607,6 +6607,16 @@
return mTransformation instanceof PasswordTransformationMethod;
}
+ /**
+ * Returns true if the current inputType is any type of password.
+ *
+ * @hide
+ */
+ public boolean isAnyPasswordInputType() {
+ final int inputType = getInputType();
+ return isPasswordInputType(inputType) || isVisiblePasswordInputType(inputType);
+ }
+
static boolean isPasswordInputType(int inputType) {
final int variation =
inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION);
diff --git a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
index d50826f..fa567f2 100644
--- a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
@@ -452,7 +452,7 @@
mEmptyStateView = rootView.findViewById(R.id.resolver_empty_state);
}
- private ViewGroup getEmptyStateView() {
+ protected ViewGroup getEmptyStateView() {
return mEmptyStateView;
}
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index c099301..5620bff 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -2411,6 +2411,8 @@
mChooserMultiProfilePagerAdapter.getActiveAdapterView()
.setAdapter(mChooserMultiProfilePagerAdapter.getCurrentRootAdapter());
return;
+ } else if (mChooserMultiProfilePagerAdapter.getCurrentUserHandle() != getUser()) {
+ return;
}
getMainThreadHandler().post(() -> {
@@ -2455,39 +2457,46 @@
offset += tabDivider.getHeight();
}
- int directShareHeight = 0;
- rowsToShow = Math.min(4, rowsToShow);
- mLastNumberOfChildren = recyclerView.getChildCount();
- for (int i = 0, childCount = recyclerView.getChildCount();
- i < childCount && rowsToShow > 0; i++) {
- View child = recyclerView.getChildAt(i);
- if (((GridLayoutManager.LayoutParams)
- child.getLayoutParams()).getSpanIndex() != 0) {
- continue;
+ if (recyclerView.getVisibility() == View.VISIBLE) {
+ int directShareHeight = 0;
+ rowsToShow = Math.min(4, rowsToShow);
+ mLastNumberOfChildren = recyclerView.getChildCount();
+ for (int i = 0, childCount = recyclerView.getChildCount();
+ i < childCount && rowsToShow > 0; i++) {
+ View child = recyclerView.getChildAt(i);
+ if (((GridLayoutManager.LayoutParams)
+ child.getLayoutParams()).getSpanIndex() != 0) {
+ continue;
+ }
+ int height = child.getHeight();
+ offset += height;
+
+ if (gridAdapter.getTargetType(
+ recyclerView.getChildAdapterPosition(child))
+ == ChooserListAdapter.TARGET_SERVICE) {
+ directShareHeight = height;
+ }
+ rowsToShow--;
}
- int height = child.getHeight();
- offset += height;
- if (gridAdapter.getTargetType(
- recyclerView.getChildAdapterPosition(child))
- == ChooserListAdapter.TARGET_SERVICE) {
- directShareHeight = height;
+ boolean isExpandable = getResources().getConfiguration().orientation
+ == Configuration.ORIENTATION_PORTRAIT && !isInMultiWindowMode();
+ if (directShareHeight != 0 && isSendAction(getTargetIntent())
+ && isExpandable) {
+ // make sure to leave room for direct share 4->8 expansion
+ int requiredExpansionHeight =
+ (int) (directShareHeight / DIRECT_SHARE_EXPANSION_RATE);
+ int topInset = mSystemWindowInsets != null ? mSystemWindowInsets.top : 0;
+ int minHeight = bottom - top - mResolverDrawerLayout.getAlwaysShowHeight()
+ - requiredExpansionHeight - topInset - bottomInset;
+
+ offset = Math.min(offset, minHeight);
}
- rowsToShow--;
- }
-
- boolean isExpandable = getResources().getConfiguration().orientation
- == Configuration.ORIENTATION_PORTRAIT && !isInMultiWindowMode();
- if (directShareHeight != 0 && isSendAction(getTargetIntent())
- && isExpandable) {
- // make sure to leave room for direct share 4->8 expansion
- int requiredExpansionHeight =
- (int) (directShareHeight / DIRECT_SHARE_EXPANSION_RATE);
- int topInset = mSystemWindowInsets != null ? mSystemWindowInsets.top : 0;
- int minHeight = bottom - top - mResolverDrawerLayout.getAlwaysShowHeight()
- - requiredExpansionHeight - topInset - bottomInset;
-
- offset = Math.min(offset, minHeight);
+ } else {
+ ViewGroup currentEmptyStateView = getCurrentEmptyStateView();
+ if (currentEmptyStateView.getVisibility() == View.VISIBLE) {
+ offset += currentEmptyStateView.getHeight();
+ }
}
mResolverDrawerLayout.setCollapsibleHeightReserved(Math.min(offset, bottom - top));
@@ -2495,6 +2504,11 @@
}
}
+ private ViewGroup getCurrentEmptyStateView() {
+ int currentPage = mChooserMultiProfilePagerAdapter.getCurrentPage();
+ return mChooserMultiProfilePagerAdapter.getItem(currentPage).getEmptyStateView();
+ }
+
static class BaseChooserTargetComparator implements Comparator<ChooserTarget> {
@Override
public int compare(ChooserTarget lhs, ChooserTarget rhs) {
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 907ea55..9218823 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -34,14 +34,14 @@
// be kept in sync with frameworks/native/libs/binder/include/binder/IAppOpsService.h
// and not be reordered
int checkOperation(int code, int uid, String packageName);
- int noteOperation(int code, int uid, String packageName, @nullable String featureId,
+ int noteOperation(int code, int uid, String packageName, @nullable String attributionTag,
boolean shouldCollectAsyncNotedOp, String message);
int startOperation(IBinder clientId, int code, int uid, String packageName,
- @nullable String featureId, boolean startIfModeDefault,
+ @nullable String attributionTag, boolean startIfModeDefault,
boolean shouldCollectAsyncNotedOp, String message);
@UnsupportedAppUsage
void finishOperation(IBinder clientId, int code, int uid, String packageName,
- @nullable String featureId);
+ @nullable String attributionTag);
void startWatchingMode(int op, String packageName, IAppOpsCallback callback);
void stopWatchingMode(IAppOpsCallback callback);
int permissionToOpCode(String permission);
@@ -52,8 +52,8 @@
// Any new method exposed to native must be added after the last one, do not reorder
int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
- String proxiedFeatureId, int proxyUid, String proxyPackageName,
- String proxyFeatureId, boolean shouldCollectAsyncNotedOp, String message);
+ String proxiedAttributionTag, int proxyUid, String proxyPackageName,
+ String proxyAttributionTag, boolean shouldCollectAsyncNotedOp, String message);
// Remaining methods are only used in Java.
int checkPackage(int uid, String packageName);
@@ -64,10 +64,10 @@
List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops);
@UnsupportedAppUsage
List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops);
- void getHistoricalOps(int uid, String packageName, String featureId, in List<String> ops,
+ void getHistoricalOps(int uid, String packageName, String attributionTag, in List<String> ops,
int filter, long beginTimeMillis, long endTimeMillis, int flags,
in RemoteCallback callback);
- void getHistoricalOpsFromDiskRaw(int uid, String packageName, String featureId,
+ void getHistoricalOpsFromDiskRaw(int uid, String packageName, String attributionTag,
in List<String> ops, int filter, long beginTimeMillis, long endTimeMillis, int flags,
in RemoteCallback callback);
void offsetHistory(long duration);
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index 4c203d3..523ed6f 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -164,6 +164,30 @@
boolean clearOverride(long changeId, String packageName);
/**
+ * Enable all compatibility changes which have enabledAfterTargetSdk ==
+ * {@param targetSdkVersion} for an app, subject to the policy. Kills the app to allow the
+ * changes to take effect.
+ *
+ * @param packageName The package name of the app whose compatibility changes will be enabled.
+ * @param targetSdkVersion The targetSdkVersion for filtering the changes to be enabled.
+ *
+ * @return The number of changes that were enabled.
+ */
+ int enableTargetSdkChanges(in String packageName, int targetSdkVersion);
+
+ /**
+ * Disable all compatibility changes which have enabledAfterTargetSdk ==
+ * {@param targetSdkVersion} for an app, subject to the policy. Kills the app to allow the
+ * changes to take effect.
+ *
+ * @param packageName The package name of the app whose compatibility changes will be disabled.
+ * @param targetSdkVersion The targetSdkVersion for filtering the changes to be disabled.
+ *
+ * @return The number of changes that were disabled.
+ */
+ int disableTargetSdkChanges(in String packageName, int targetSdkVersion);
+
+ /**
* Revert overrides to compatibility changes. Kills the app to allow the changes to take effect.
*
* @param packageName The package name of the app whose overrides will be cleared.
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index 73ef8c6..2f048c9 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -430,7 +430,7 @@
if (shouldHide(file)) continue;
if (file.isDirectory()) {
- for (File child : file.listFiles()) {
+ for (File child : FileUtils.listFilesOrEmpty(file)) {
pending.add(child);
}
}
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index 91ef0b5..1296ddc 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -116,6 +116,7 @@
NETWORK_STATUS,
context.getString(R.string.notification_channel_network_status),
NotificationManager.IMPORTANCE_LOW);
+ network.setBlockableSystem(true);
channelsList.add(network);
final NotificationChannel networkAlertsChannel = new NotificationChannel(
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 94924a5..633aa2c 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -140,6 +140,33 @@
*/
public static final int MEMORY_TAG_LEVEL_SYNC = 3 << 19;
+ /**
+ * A two-bit field for GWP-ASan level of this process. See the possible values below.
+ */
+ public static final int GWP_ASAN_LEVEL_MASK = (1 << 21) | (1 << 22);
+
+ /**
+ * Disable GWP-ASan in this process.
+ * GWP-ASan is a low-overhead memory bug detector using guard pages on a small
+ * subset of heap allocations.
+ */
+ public static final int GWP_ASAN_LEVEL_NEVER = 0 << 21;
+
+ /**
+ * Enable GWP-ASan in this process with a small sampling rate.
+ * With approx. 1% chance GWP-ASan will be activated and apply its protection
+ * to a small subset of heap allocations.
+ * Otherwise (~99% chance) this process is unaffected.
+ */
+ public static final int GWP_ASAN_LEVEL_LOTTERY = 1 << 21;
+
+ /**
+ * Always enable GWP-ASan in this process.
+ * GWP-ASan is activated unconditionally (but still, only a small subset of
+ * allocations is protected).
+ */
+ public static final int GWP_ASAN_LEVEL_ALWAYS = 2 << 21;
+
/** No external storage should be mounted. */
public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE;
/** Default external storage should be mounted. */
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 54cf693..0bfd659 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -125,12 +125,6 @@
private static boolean sPreloadComplete;
- /**
- * Cached classloader to use for the system server. Will only be populated in the system
- * server process.
- */
- private static ClassLoader sCachedSystemServerClassLoader = null;
-
static void preload(TimingsTraceLog bootTimingsTraceLog) {
Log.d(TAG, "begin preload");
bootTimingsTraceLog.traceBegin("BeginPreload");
@@ -508,13 +502,7 @@
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
- if (performSystemServerDexOpt(systemServerClasspath)) {
- // Throw away the cached classloader. If we compiled here, the classloader would
- // not have had AoT-ed artifacts.
- // Note: This only works in a very special environment where selinux enforcement is
- // disabled, e.g., Mac builds.
- sCachedSystemServerClassLoader = null;
- }
+ performSystemServerDexOpt(systemServerClasspath);
// Capturing profiles is only supported for debug or eng builds since selinux normally
// prevents it.
if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
@@ -546,9 +534,10 @@
throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
} else {
- createSystemServerClassLoader();
- ClassLoader cl = sCachedSystemServerClassLoader;
- if (cl != null) {
+ ClassLoader cl = null;
+ if (systemServerClasspath != null) {
+ cl = createPathClassLoader(systemServerClasspath, parsedArgs.mTargetSdkVersion);
+
Thread.currentThread().setContextClassLoader(cl);
}
@@ -564,24 +553,6 @@
}
/**
- * Create the classloader for the system server and store it in
- * {@link sCachedSystemServerClassLoader}. This function may be called through JNI in
- * system server startup, when the runtime is in a critically low state. Do not do
- * extended computation etc here.
- */
- private static void createSystemServerClassLoader() {
- if (sCachedSystemServerClassLoader != null) {
- return;
- }
- final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
- // TODO: Should we run optimization here?
- if (systemServerClasspath != null) {
- sCachedSystemServerClassLoader = createPathClassLoader(systemServerClasspath,
- VMRuntime.SDK_VERSION_CUR_DEVELOPMENT);
- }
- }
-
- /**
* Note that preparing the profiles for system server does not require special selinux
* permissions. From the installer perspective the system server is a regular package which can
* capture profile information.
@@ -645,16 +616,15 @@
/**
* Performs dex-opt on the elements of {@code classPath}, if needed. We choose the instruction
- * set of the current runtime. If something was compiled, return true.
+ * set of the current runtime.
*/
- private static boolean performSystemServerDexOpt(String classPath) {
+ private static void performSystemServerDexOpt(String classPath) {
final String[] classPathElements = classPath.split(":");
final IInstalld installd = IInstalld.Stub
.asInterface(ServiceManager.getService("installd"));
final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();
String classPathForElement = "";
- boolean compiledSomething = false;
for (String classPathElement : classPathElements) {
// We default to the verify filter because the compilation will happen on /data and
// system server cannot load executable code outside /system.
@@ -695,7 +665,6 @@
uuid, classLoaderContext, seInfo, false /* downgrade */,
targetSdkVersion, /*profileName*/ null, /*dexMetadataPath*/ null,
"server-dexopt");
- compiledSomething = true;
} catch (RemoteException | ServiceSpecificException e) {
// Ignore (but log), we need this on the classpath for fallback mode.
Log.w(TAG, "Failed compiling classpath element for system server: "
@@ -706,8 +675,6 @@
classPathForElement = encodeSystemServerClassPath(
classPathForElement, classPathElement);
}
-
- return compiledSomething;
}
/**
diff --git a/core/java/com/android/internal/util/Parcelling.java b/core/java/com/android/internal/util/Parcelling.java
index 7f567b9..dd64c40 100644
--- a/core/java/com/android/internal/util/Parcelling.java
+++ b/core/java/com/android/internal/util/Parcelling.java
@@ -221,6 +221,33 @@
}
}
+ class ForInternedStringArraySet implements Parcelling<ArraySet<String>> {
+ @Override
+ public void parcel(ArraySet<String> item, Parcel dest, int parcelFlags) {
+ if (item == null) {
+ dest.writeInt(-1);
+ } else {
+ dest.writeInt(item.size());
+ for (String string : item) {
+ dest.writeString(string);
+ }
+ }
+ }
+
+ @Override
+ public ArraySet<String> unparcel(Parcel source) {
+ final int size = source.readInt();
+ if (size < 0) {
+ return null;
+ }
+ ArraySet<String> set = new ArraySet<>();
+ for (int count = 0; count < size; count++) {
+ set.add(TextUtils.safeIntern(source.readString()));
+ }
+ return set;
+ }
+ }
+
class ForBoolean implements Parcelling<Boolean> {
@Override
public void parcel(@Nullable Boolean item, Parcel dest, int parcelFlags) {
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 5dd3389b..47f094f 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -116,7 +116,8 @@
}
@Override
- public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, boolean sync) {
+ public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, float zoom,
+ boolean sync) {
if (sync) {
try {
mSession.wallpaperOffsetsComplete(asBinder());
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 0d0dc3e..f7c6dbd 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -853,8 +853,11 @@
} cfg_state = CONFIG_UNKNOWN;
if (cfg_state == CONFIG_UNKNOWN) {
- const std::map<std::string, std::string> configs =
- vintf::VintfObject::GetInstance()->getRuntimeInfo()->kernelConfigs();
+ auto runtime_info = vintf::VintfObject::GetInstance()
+ ->getRuntimeInfo(false /* skip cache */,
+ vintf::RuntimeInfo::FetchFlag::CONFIG_GZ);
+ CHECK(runtime_info != nullptr) << "Kernel configs cannot be fetched. b/151092221";
+ const std::map<std::string, std::string>& configs = runtime_info->kernelConfigs();
std::map<std::string, std::string>::const_iterator it = configs.find("CONFIG_VMAP_STACK");
cfg_state = (it != configs.end() && it->second == "y") ? CONFIG_SET : CONFIG_UNSET;
}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 2128f99..dafb377 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -121,16 +121,11 @@
static pid_t gSystemServerPid = 0;
static constexpr const char* kPropFuse = "persist.sys.fuse";
-static constexpr const char* kZygoteClassName = "com/android/internal/os/Zygote";
-
+static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
static jclass gZygoteClass;
static jmethodID gCallPostForkSystemServerHooks;
static jmethodID gCallPostForkChildHooks;
-static constexpr const char* kZygoteInitClassName = "com/android/internal/os/ZygoteInit";
-static jclass gZygoteInitClass;
-static jmethodID gCreateSystemServerClassLoader;
-
static bool gIsSecurityEnforced = true;
/**
@@ -356,10 +351,14 @@
// Must match values in com.android.internal.os.Zygote.
enum RuntimeFlags : uint32_t {
- DEBUG_ENABLE_JDWP = 1,
- PROFILE_FROM_SHELL = 1 << 15,
- MEMORY_TAG_LEVEL_MASK = (1 << 19) | (1 << 20),
- MEMORY_TAG_LEVEL_TBI = 1 << 19,
+ DEBUG_ENABLE_JDWP = 1,
+ PROFILE_FROM_SHELL = 1 << 15,
+ MEMORY_TAG_LEVEL_MASK = (1 << 19) | (1 << 20),
+ MEMORY_TAG_LEVEL_TBI = 1 << 19,
+ GWP_ASAN_LEVEL_MASK = (1 << 21) | (1 << 22),
+ GWP_ASAN_LEVEL_NEVER = 0 << 21,
+ GWP_ASAN_LEVEL_LOTTERY = 1 << 21,
+ GWP_ASAN_LEVEL_ALWAYS = 2 << 21,
};
enum UnsolicitedZygoteMessageTypes : uint32_t {
@@ -1741,6 +1740,18 @@
}
android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &heap_tagging_level, sizeof(heap_tagging_level));
+ bool forceEnableGwpAsan = false;
+ switch (runtime_flags & RuntimeFlags::GWP_ASAN_LEVEL_MASK) {
+ default:
+ case RuntimeFlags::GWP_ASAN_LEVEL_NEVER:
+ break;
+ case RuntimeFlags::GWP_ASAN_LEVEL_ALWAYS:
+ forceEnableGwpAsan = true;
+ [[fallthrough]];
+ case RuntimeFlags::GWP_ASAN_LEVEL_LOTTERY:
+ android_mallopt(M_INITIALIZE_GWP_ASAN, &forceEnableGwpAsan, sizeof(forceEnableGwpAsan));
+ }
+
if (NeedsNoRandomizeWorkaround()) {
// Work around ARM kernel ASLR lossage (http://b/5817320).
int old_personality = personality(0xffffffff);
@@ -1780,15 +1791,6 @@
fail_fn("Error calling post fork system server hooks.");
}
- // Prefetch the classloader for the system server. This is done early to
- // allow a tie-down of the proper system server selinux domain.
- env->CallStaticVoidMethod(gZygoteInitClass, gCreateSystemServerClassLoader);
- if (env->ExceptionCheck()) {
- // Be robust here. The Java code will attempt to create the classloader
- // at a later point (but may not have rights to use AoT artifacts).
- env->ExceptionClear();
- }
-
// TODO(oth): Remove hardcoded label here (b/117874058).
static const char* kSystemServerLabel = "u:r:system_server:s0";
if (selinux_android_setcon(kSystemServerLabel) != 0) {
@@ -2466,13 +2468,6 @@
gCallPostForkChildHooks = GetStaticMethodIDOrDie(env, gZygoteClass, "callPostForkChildHooks",
"(IZZLjava/lang/String;)V");
- gZygoteInitClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, kZygoteInitClassName));
- gCreateSystemServerClassLoader = GetStaticMethodIDOrDie(env, gZygoteInitClass,
- "createSystemServerClassLoader",
- "()V");
-
- RegisterMethodsOrDie(env, "com/android/internal/os/Zygote", gMethods, NELEM(gMethods));
-
- return JNI_OK;
+ return RegisterMethodsOrDie(env, "com/android/internal/os/Zygote", gMethods, NELEM(gMethods));
}
} // namespace android
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 030483b..ef6eb38 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -724,6 +724,16 @@
// CATEGORY: SETTINGS
// OS: R
ACTION_ADB_WIRELESS_OFF = 1735;
+
+ // ACTION: Change Wi-Fi hotspot name
+ // CATEGORY: SETTINGS
+ // OS: R
+ ACTION_SETTINGS_CHANGE_WIFI_HOTSPOT_NAME = 1736;
+
+ // ACTION: Change Wi-Fi hotspot password
+ // CATEGORY: SETTINGS
+ // OS: R
+ ACTION_SETTINGS_CHANGE_WIFI_HOTSPOT_PASSWORD = 1737;
}
/**
diff --git a/core/proto/android/content/package_item_info.proto b/core/proto/android/content/package_item_info.proto
index 4a7d043..e8ae1b3 100644
--- a/core/proto/android/content/package_item_info.proto
+++ b/core/proto/android/content/package_item_info.proto
@@ -109,6 +109,7 @@
}
optional int32 network_security_config_res = 17;
optional int32 category = 18;
+ optional bool enable_gwp_asan = 19;
}
optional Detail detail = 17;
}
diff --git a/core/proto/android/telephony/enums.proto b/core/proto/android/telephony/enums.proto
index 4777169..f14e3ed 100644
--- a/core/proto/android/telephony/enums.proto
+++ b/core/proto/android/telephony/enums.proto
@@ -20,6 +20,43 @@
option java_outer_classname = "TelephonyProtoEnums";
option java_multiple_files = true;
+enum CallBearerEnum {
+ /** Call bearer is unknown or invalid */
+ CALL_BEARER_UNKNOWN = 0;
+
+ /** Call bearer is legacy CS */
+ CALL_BEARER_CS = 1;
+
+ /** Call bearer is IMS */
+ CALL_BEARER_IMS = 2;
+}
+
+enum CallDirectionEnum {
+ /** Call direction: unknown or invalid */
+ CALL_DIRECTION_UNKNOWN = 0;
+
+ /** Call direction: mobile originated (outgoing for this device) */
+ CALL_DIRECTION_MO = 1;
+
+ /** Call direction: mobile terminated (incoming for this device) */
+ CALL_DIRECTION_MT = 2;
+}
+
+// Call setup duration buckets.
+// See com.android.internal.telephony.metrics.VoiceCallSessionStats for definition.
+enum CallSetupDurationEnum {
+ CALL_SETUP_DURATION_UNKNOWN = 0;
+ CALL_SETUP_DURATION_EXTREMELY_FAST = 1;
+ CALL_SETUP_DURATION_ULTRA_FAST = 2;
+ CALL_SETUP_DURATION_VERY_FAST = 3;
+ CALL_SETUP_DURATION_FAST = 4;
+ CALL_SETUP_DURATION_NORMAL = 5;
+ CALL_SETUP_DURATION_SLOW = 6;
+ CALL_SETUP_DURATION_VERY_SLOW = 7;
+ CALL_SETUP_DURATION_ULTRA_SLOW = 8;
+ CALL_SETUP_DURATION_EXTREMELY_SLOW = 9;
+}
+
// Data conn. power states, primarily used by android/telephony/DataConnectionRealTimeInfo.java.
enum DataConnectionPowerStateEnum {
DATA_CONNECTION_POWER_STATE_LOW = 1;
@@ -63,7 +100,6 @@
SIGNAL_STRENGTH_GREAT = 4;
}
-
enum ServiceStateEnum {
/**
* Normal operation condition, the phone is registered
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0dd3ad6..4001def 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -5003,15 +5003,15 @@
<permission android:name="android.permission.ACCESS_LOCUS_ID_USAGE_STATS"
android:protectionLevel="signature|appPredictor" />
- <!-- Feature Id for Country Detector. -->
- <feature android:featureId="CountryDetector" android:label="@string/country_detector"/>
- <!-- Feature Id for Location service. -->
- <feature android:featureId="LocationService" android:label="@string/location_service"/>
- <!-- Feature Id for Sensor Notification service. -->
- <feature android:featureId="SensorNotificationService"
+ <!-- Attribution for Country Detector. -->
+ <attribution android:tag="CountryDetector" android:label="@string/country_detector"/>
+ <!-- Attribution for Location service. -->
+ <attribution android:tag="LocationService" android:label="@string/location_service"/>
+ <!-- Attribution for Sensor Notification service. -->
+ <attribution android:tag="SensorNotificationService"
android:label="@string/sensor_notification_service"/>
<!-- Feature Id for Twilight service. -->
- <feature android:featureId="TwilightService" android:label="@string/twilight_service"/>
+ <attribution android:tag="TwilightService" android:label="@string/twilight_service"/>
<application android:process="system"
android:persistent="true"
@@ -5200,6 +5200,7 @@
<activity android:name="com.android.internal.app.BlockedAppActivity"
android:theme="@style/Theme.Dialog.Confirmation"
android:excludeFromRecents="true"
+ android:lockTaskMode="always"
android:process=":ui">
</activity>
diff --git a/core/res/res/layout-car/car_resolver_different_item_header.xml b/core/res/res/layout-car/car_resolver_different_item_header.xml
deleted file mode 100644
index 222ecc6..0000000
--- a/core/res/res/layout-car/car_resolver_different_item_header.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * 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.
- */
--->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alwaysShow="true"
- android:text="@*android:string/use_a_different_app"
- android:minHeight="56dp"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:gravity="start|center_vertical"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:elevation="8dp"
-/>
\ No newline at end of file
diff --git a/core/res/res/layout-car/car_resolver_list.xml b/core/res/res/layout-car/car_resolver_list.xml
index 15a8645..755cbfe 100644
--- a/core/res/res/layout-car/car_resolver_list.xml
+++ b/core/res/res/layout-car/car_resolver_list.xml
@@ -23,90 +23,142 @@
android:id="@id/contentPanel">
<LinearLayout
- android:id="@+id/button_bar"
- android:visibility="gone"
- style="?attr/buttonBarStyle"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_ignoreOffset="true"
- android:layout_alwaysShow="true"
- android:layout_hasNestedScrollIndicator="true"
- android:background="?attr/colorBackgroundFloating"
- android:orientation="horizontal"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:paddingStart="12dp"
+ android:layout_height="match_parent"
android:weightSum="5"
- android:paddingEnd="12dp"
+ android:layout_alwaysShow="true"
+ android:orientation="vertical"
+ android:background="?attr/colorBackgroundFloating"
android:elevation="8dp">
- <TextView
- android:id="@+id/profile_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginEnd="8dp"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
- android:textSize="40sp"
- android:layout_weight="5"
- android:layout_gravity = "left"
+ <LinearLayout
+ android:id="@+id/button_bar"
android:visibility="gone"
- android:textColor="?attr/colorAccent"
- android:singleLine="true"/>
-
- <TextView
- android:id="@+id/title"
- android:layout_width="wrap_content"
+ style="?attr/buttonBarStyle"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:minHeight="56dp"
- android:layout_gravity = "left"
- android:layout_weight="3"
+ android:layout_ignoreOffset="true"
+ android:layout_alwaysShow="true"
+ android:layout_hasNestedScrollIndicator="true"
+ android:background="?attr/colorBackgroundFloating"
+ android:orientation="horizontal"
android:paddingTop="8dp"
- android:layout_below="@id/profile_button"
- android:paddingBottom="8dp"/>
+ android:paddingStart="12dp"
+ android:weightSum="4"
+ android:paddingEnd="12dp"
+ android:elevation="8dp">
- <Button
- android:id="@+id/button_once"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:enabled="false"
- android:layout_gravity = "right"
- android:text="@string/activity_resolver_use_once"
- android:layout_weight="1"
- android:onClick="onButtonClick"/>
+ <TextView
+ android:id="@+id/profile_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
+ android:textSize="40sp"
+ android:layout_weight="4"
+ android:layout_gravity="left"
+ android:visibility="gone"
+ android:textColor="?attr/colorAccent"
+ android:singleLine="true"/>
- <Button
- android:id="@+id/button_always"
- android:layout_marginLeft="10dp"
- android:layout_width="wrap_content"
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left"
+ android:layout_weight="3"
+ android:paddingTop="8dp"
+ android:layout_below="@id/profile_button"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:paddingBottom="8dp"/>
+
+ <Button
+ android:id="@+id/button_once"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:enabled="false"
+ android:layout_gravity="right"
+ style="?attr/buttonBarButtonStyle"
+ android:text="@string/activity_resolver_use_once"
+ android:layout_weight="0.5"
+ android:onClick="onButtonClick"/>
+
+ <Button
+ android:id="@+id/button_always"
+ android:layout_marginLeft="2dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:enabled="false"
+ android:layout_gravity="right"
+ style="?attr/buttonBarButtonStyle"
+ android:text="@string/activity_resolver_use_always"
+ android:layout_weight="0.5"
+ android:onClick="onButtonClick"/>
+ </LinearLayout>
+
+ <FrameLayout
+ android:id="@+id/stub"
+ android:visibility="gone"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:enabled="false"
- android:layout_gravity = "right"
- android:text="@string/activity_resolver_use_always"
- android:layout_weight="1"
- android:onClick="onButtonClick"/>
+ android:background="?attr/colorBackgroundFloating"/>
+
+ <TabHost
+ android:id="@+id/profile_tabhost"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:background="?attr/colorBackgroundFloating">
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <TabWidget
+ android:id="@android:id/tabs"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone">
+ </TabWidget>
+ <View
+ android:id="@+id/resolver_tab_divider"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="?attr/colorBackgroundFloating"
+ android:foreground="?attr/dividerVertical"
+ android:layout_marginBottom="8dp"/>
+ <FrameLayout
+ android:id="@android:id/tabcontent"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <com.android.internal.app.ResolverViewPager
+ android:id="@+id/profile_pager"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+ </FrameLayout>
+ </LinearLayout>
+ </TabHost>
+
+ <View
+ android:layout_alwaysShow="true"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="?attr/colorBackgroundFloating"
+ android:foreground="?attr/dividerVertical"/>
+
+ <TextView android:id="@+id/empty"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?attr/colorBackgroundFloating"
+ android:elevation="8dp"
+ android:layout_alwaysShow="true"
+ android:text="@string/noApplications"
+ android:padding="32dp"
+ android:gravity="center"
+ android:visibility="gone"/>
+
</LinearLayout>
- <ListView
- android:layout_width="match_parent"
- android:layout_height="500dp"
- android:id="@+id/resolver_list"
- android:clipToPadding="false"
- android:scrollbarStyle="outsideOverlay"
- android:background="?attr/colorBackgroundFloating"
- android:elevation="8dp"
- android:nestedScrollingEnabled="true"
- android:scrollIndicators="top|bottom"/>
-
- <TextView android:id="@+id/empty"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="?attr/colorBackgroundFloating"
- android:elevation="8dp"
- android:layout_alwaysShow="true"
- android:text="@string/noApplications"
- android:padding="32dp"
- android:gravity="center"
- android:visibility="gone"/>
-
</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/layout-car/car_resolver_list_with_default.xml b/core/res/res/layout-car/car_resolver_list_with_default.xml
index 2aed00b..5e450b2 100644
--- a/core/res/res/layout-car/car_resolver_list_with_default.xml
+++ b/core/res/res/layout-car/car_resolver_list_with_default.xml
@@ -40,12 +40,12 @@
<ImageView
android:id="@+id/icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
+ android:layout_width="60dp"
+ android:layout_height="60dp"
android:layout_gravity="start|top"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
- android:layout_marginTop="20dp"
+ android:layout_marginStart="10dp"
+ android:layout_marginEnd="5dp"
+ android:layout_marginTop="10dp"
android:src="@drawable/resolver_icon_placeholder"
android:scaleType="fitCenter"/>
@@ -55,7 +55,7 @@
android:layout_weight="1"
android:layout_height="?attr/listPreferredItemHeight"
android:layout_marginStart="16dp"
- android:textAppearance="?attr/textAppearanceMedium"
+ android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="start|center_vertical"
android:paddingEnd="16dp"/>
@@ -120,7 +120,7 @@
android:layout_width="wrap_content"
android:layout_gravity="start"
android:maxLines="2"
- style="?attr/buttonBarNegativeButtonStyle"
+ style="?attr/buttonBarButtonStyle"
android:minHeight="@dimen/alert_dialog_button_bar_height"
android:layout_height="wrap_content"
android:enabled="false"
@@ -133,29 +133,64 @@
android:layout_gravity="end"
android:maxLines="2"
android:minHeight="@dimen/alert_dialog_button_bar_height"
- style="?attr/buttonBarPositiveButtonStyle"
+ style="?attr/buttonBarButtonStyle"
android:layout_height="wrap_content"
android:enabled="false"
android:text="@string/activity_resolver_use_always"
android:onClick="onButtonClick"/>
</LinearLayout>
+ <FrameLayout
+ android:id="@+id/stub"
+ android:layout_alwaysShow="true"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?attr/colorBackgroundFloating"/>
+
+ <TabHost
+ android:layout_alwaysShow="true"
+ android:id="@+id/profile_tabhost"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:background="?attr/colorBackgroundFloating">
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <TabWidget
+ android:id="@android:id/tabs"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone">
+ </TabWidget>
+ <View
+ android:id="@+id/resolver_tab_divider"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="?attr/colorBackgroundFloating"
+ android:foreground="?attr/dividerVertical"
+ android:layout_marginBottom="8dp"/>
+ <FrameLayout
+ android:id="@android:id/tabcontent"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <com.android.internal.app.ResolverViewPager
+ android:id="@+id/profile_pager"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ </com.android.internal.app.ResolverViewPager>
+ </FrameLayout>
+ </LinearLayout>
+ </TabHost>
+
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/dividerVertical"/>
-
- <ListView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:id="@+id/resolver_list"
- android:layout_weight="4"
- android:clipToPadding="false"
- android:scrollbarStyle="outsideOverlay"
- android:background="?attr/colorBackgroundFloating"
- android:elevation="8dp"
- android:nestedScrollingEnabled="true"
- android:divider="@null"/>
</LinearLayout>
</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index e17fc8a..b754e0c 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -100,8 +100,7 @@
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/colorBackgroundFloating"
- android:foreground="?attr/dividerVertical"
- android:layout_marginBottom="@dimen/resolver_tab_divider_bottom_padding"/>
+ android:foreground="?attr/dividerVertical"/>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
index 0d4523a..06a7633 100644
--- a/core/res/res/layout/resolver_list_with_default.xml
+++ b/core/res/res/layout/resolver_list_with_default.xml
@@ -183,8 +183,7 @@
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/colorBackgroundFloating"
- android:foreground="?attr/dividerVertical"
- android:layout_marginBottom="@dimen/resolver_tab_divider_bottom_padding"/>
+ android:foreground="?attr/dividerVertical"/>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index c245131..cb88aee 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1541,6 +1541,28 @@
<flag name="microphone" value="0x80" />
</attr>
+ <!-- Enable sampled memory bug detection in this process.
+ When enabled, a very small, random subset of native
+ memory allocations are protected with guard pages, providing an
+ ASan-like error report in case of a memory corruption bug.
+
+ GWP-ASan is a recursive acronym. It stands for “GWP-ASan Will Provide Allocation SANity”.
+ See the <a href="http://llvm.org/docs/GwpAsan.html">LLVM documentation</a>
+ for more information about this feature.
+
+ <p>This tag can be applied to any tag that allows
+ {@link android.R.styleable#AndroidManifestProcess process} tag:
+ {@link android.R.styleable#AndroidManifestApplication application} tag (to supply
+ a default setting for all application components), or with the
+ {@link android.R.styleable#AndroidManifestProvider provider},
+ {@link android.R.styleable#AndroidManifestService service},
+ {@link android.R.styleable#AndroidManifestReceiver receiver},
+ {@link android.R.styleable#AndroidManifestActivity activity} tag.
+ When multiple components run in the same process,
+ the first component to start determines the behavior of the entire process.
+
+ The default value is {@code false}. -->
+ <attr name="enableGwpAsan" format="boolean" />
<!-- The <code>manifest</code> tag is the root of an
<code>AndroidManifest.xml</code> file,
@@ -1552,7 +1574,7 @@
<code>com.google.app.<em>appname</em></code>
<p>Inside of the manifest tag, may appear the following tags
- in any order: {@link #AndroidManifestFeature feature},
+ in any order: {@link #AndroidManifestAttribution attribution},
{@link #AndroidManifestPermission permission},
{@link #AndroidManifestPermissionGroup permission-group},
{@link #AndroidManifestPermissionTree permission-tree},
@@ -1806,31 +1828,38 @@
The default value is {@code true}. -->
<attr name="allowNativeHeapPointerTagging" format="boolean" />
+
+ <attr name="enableGwpAsan" />
+
</declare-styleable>
- <!-- The <code>feature</code> tag declares a feature. A feature is a logical part of an app.
- E.g. photo sharing app might include a direct messaging component. To tag certain code as
- belonging to a feature, use a context created via
- {@link android.content.Context#createFeatureContext(String)} for any interaction with the
+ <!-- An attribution is a logical part of an app and is identified by a tag.
+ E.g. a photo sharing app might include a direct messaging component. To tag certain code as
+ belonging to an attribution, use a context created via
+ {@link android.content.Context#createAttributionContext(String)} for any interaction with the
system.
<p>This appears as a child tag of the root {@link #AndroidManifest manifest} tag.
- <p>In case this feature inherits from another feature, this tag can contain one or multiple
- {@link #AndroidManifestFeatureInheritFrom inherit-from} tags. -->
- <declare-styleable name="AndroidManifestFeature" parent="AndroidManifest">
- <!-- Required identifier for a feature. Can be passed to
- {@link android.content.Context#createFeatureContext} to create a context for this feature
- -->
+ <p>In case this attribution inherits from another attribution, this tag can contain one or
+ multiple {@link #AndroidManifestAttributionInheritFrom inherit-from} tags. -->
+ <declare-styleable name="AndroidManifestAttribution" parent="AndroidManifest">
+ <!-- TODO moltmann: Remove -->
<attr name="featureId" format="string" />
- <!-- Required user visible label for a feature. -->
+ <!-- Required identifier for a attribution. Can be passed to
+ {@link android.content.Context#createAttributionContext} to create a context tagged with
+ this attribution
+ -->
+ <attr name="tag" format="string" />
+ <!-- Required user visible label for a attribution. -->
<attr name="label" format="string" />
</declare-styleable>
<!-- Declares previously declared features this feature inherits from. -->
- <declare-styleable name="AndroidManifestFeatureInheritFrom" parent="AndroidManifestFeature">
- <!-- Identifier of the feature this feature inherits from -->
- <attr name="featureId" format="string" />
+ <declare-styleable name="AndroidManifestAttributionInheritFrom"
+ parent="AndroidManifestAttribution">
+ <!-- Identifier of the attribution this attribution inherits from -->
+ <attr name="tag" format="string" />
</declare-styleable>
<!-- The <code>permission</code> tag declares a security permission that can be
@@ -2312,6 +2341,7 @@
<declare-styleable name="AndroidManifestProcess" parent="AndroidManifestProcesses">
<!-- Required name of the process that is allowed -->
<attr name="process" />
+ <attr name="enableGwpAsan" />
</declare-styleable>
<!-- The <code>deny-permission</code> tag specifies that a permission is to be denied
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 617949d..6f468e0 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4418,4 +4418,7 @@
<!-- Package name of custom session policy provider class used by MediaSessionService. -->
<string name="config_customSessionPolicyProvider"></string>
+
+ <!-- The max scale for the wallpaper when it's zoomed in -->
+ <item name="config_wallpaperMaxScale" format="float" type="dimen">1</item>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 9118617..2faa0c9 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -776,7 +776,6 @@
<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_divider_bottom_padding">8dp</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 39e8197..96807cc 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3004,6 +3004,7 @@
<public name="animatedImageDrawable"/>
<public name="htmlDescription"/>
<public name="preferMinimalPostProcessing"/>
+ <!-- @removed -->
<public name="featureId" />
<public name="supportsInlineSuggestions" />
<public name="crossProfile" />
@@ -3015,6 +3016,7 @@
<public name="allowNativeHeapPointerTagging" />
<public name="preserveLegacyExternalStorage" />
<public name="mimeGroup" />
+ <public name="enableGwpAsan" />
</public-group>
<public-group type="drawable" first-id="0x010800b5">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 826379d..a9008d7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3909,7 +3909,6 @@
<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_divider_bottom_padding" />
<!-- 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" />
@@ -3927,4 +3926,6 @@
<java-symbol type="string" name="config_customMediaKeyDispatcher" />
<java-symbol type="string" name="config_customSessionPolicyProvider" />
+ <!-- The max scale for the wallpaper when it's zoomed in -->
+ <java-symbol type="dimen" name="config_wallpaperMaxScale"/>
</resources>
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index 50cd5a3..fe25e79 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -123,7 +123,7 @@
mController = new InsetsAnimationControlImpl(controls,
new Rect(0, 0, 500, 500), mInsetsState, mMockListener, systemBars(),
mMockController, 10 /* durationMs */, new LinearInterpolator(),
- false /* fade */, LAYOUT_INSETS_DURING_ANIMATION_SHOWN, 0 /* animationType */);
+ false /* fade */, 0 /* animationType */);
}
@Test
@@ -182,7 +182,7 @@
@Test
public void testCancelled() {
- mController.onCancelled();
+ mController.cancel();
try {
mController.setInsetsAndAlpha(Insets.NONE, 1f /*alpha */, 0f /* fraction */);
fail("Expected exception to be thrown");
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 023fc17..f1ab8dd 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -31,6 +31,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -47,6 +48,7 @@
import android.graphics.Rect;
import android.os.CancellationSignal;
import android.platform.test.annotations.Presubmit;
+import android.view.InsetsState.InternalInsetsType;
import android.view.SurfaceControl.Transaction;
import android.view.WindowInsets.Type;
import android.view.WindowInsetsController.OnControllableInsetsChangedListener;
@@ -169,11 +171,8 @@
@Test
public void testControlsChanged() {
- InsetsSourceControl control =
- new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point());
- mController.onControlsChanged(new InsetsSourceControl[] { control });
- assertEquals(mLeash,
- mController.getSourceConsumer(ITYPE_STATUS_BAR).getControl().getLeash());
+ mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
+ assertNotNull(mController.getSourceConsumer(ITYPE_STATUS_BAR).getControl().getLeash());
mController.addOnControllableInsetsChangedListener(
((controller, typeMask) -> assertEquals(statusBars(), typeMask)));
}
@@ -183,9 +182,7 @@
OnControllableInsetsChangedListener listener
= mock(OnControllableInsetsChangedListener.class);
mController.addOnControllableInsetsChangedListener(listener);
- InsetsSourceControl control =
- new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point());
- mController.onControlsChanged(new InsetsSourceControl[] { control });
+ mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
mController.onControlsChanged(new InsetsSourceControl[0]);
assertNull(mController.getSourceConsumer(ITYPE_STATUS_BAR).getControl());
InOrder inOrder = Mockito.inOrder(listener);
@@ -197,9 +194,7 @@
@Test
public void testControlsRevoked_duringAnim() {
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
- InsetsSourceControl control =
- new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point());
- mController.onControlsChanged(new InsetsSourceControl[] { control });
+ mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
WindowInsetsAnimationControlListener mockListener =
mock(WindowInsetsAnimationControlListener.class);
@@ -262,11 +257,8 @@
@Test
public void testApplyImeVisibility() {
- final InsetsSourceControl ime = new InsetsSourceControl(ITYPE_IME, mLeash, new Point());
-
- InsetsSourceControl[] controls = new InsetsSourceControl[3];
- controls[0] = ime;
- mController.onControlsChanged(controls);
+ InsetsSourceControl ime = createControl(ITYPE_IME);
+ mController.onControlsChanged(new InsetsSourceControl[] { ime });
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
mController.getSourceConsumer(ITYPE_IME).onWindowFocusGained();
mController.applyImeVisibility(true);
@@ -429,9 +421,7 @@
@Test
public void testRestoreStartsAnimation() {
- InsetsSourceControl control =
- new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point());
- mController.onControlsChanged(new InsetsSourceControl[]{control});
+ mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
mController.hide(Type.statusBars());
@@ -448,7 +438,7 @@
assertTrue(mController.getState().getSource(ITYPE_STATUS_BAR).isVisible());
// Gaining control
- mController.onControlsChanged(new InsetsSourceControl[]{control});
+ mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(ITYPE_STATUS_BAR));
mController.cancelExistingAnimation();
assertFalse(mController.getSourceConsumer(ITYPE_STATUS_BAR).isRequestedVisible());
@@ -459,8 +449,6 @@
@Test
public void testStartImeAnimationAfterGettingControl() {
- InsetsSourceControl control =
- new InsetsSourceControl(ITYPE_IME, mLeash, new Point());
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
@@ -471,7 +459,7 @@
mController.show(ime(), true /* fromIme */);
// Gaining control shortly after
- mController.onControlsChanged(new InsetsSourceControl[]{control});
+ mController.onControlsChanged(createSingletonControl(ITYPE_IME));
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ITYPE_IME));
mController.cancelExistingAnimation();
@@ -483,16 +471,13 @@
@Test
public void testStartImeAnimationAfterGettingControl_imeLater() {
- InsetsSourceControl control =
- new InsetsSourceControl(ITYPE_IME, mLeash, new Point());
-
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
mController.show(ime());
assertFalse(mController.getState().getSource(ITYPE_IME).isVisible());
// Gaining control shortly after
- mController.onControlsChanged(new InsetsSourceControl[]{control});
+ mController.onControlsChanged(createSingletonControl(ITYPE_IME));
// Pretend IME is calling
mController.show(ime(), true /* fromIme */);
@@ -507,9 +492,7 @@
@Test
public void testAnimationEndState_controller() throws Exception {
- InsetsSourceControl control =
- new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point());
- mController.onControlsChanged(new InsetsSourceControl[] { control });
+ mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
WindowInsetsAnimationControlListener mockListener =
@@ -535,9 +518,7 @@
@Test
public void testCancellation_afterGainingControl() throws Exception {
- InsetsSourceControl control =
- new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point());
- mController.onControlsChanged(new InsetsSourceControl[] { control });
+ mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
WindowInsetsAnimationControlListener mockListener =
@@ -655,12 +636,23 @@
latch.await();
}
+ private InsetsSourceControl createControl(@InternalInsetsType int type) {
+
+ // Simulate binder behavior by copying SurfaceControl. Otherwise, InsetsController will
+ // attempt to release mLeash directly.
+ SurfaceControl copy = new SurfaceControl();
+ copy.copyFrom(mLeash);
+ return new InsetsSourceControl(type, copy, new Point());
+ }
+
+ private InsetsSourceControl[] createSingletonControl(@InternalInsetsType int type) {
+ return new InsetsSourceControl[] { createControl(type) };
+ }
+
private InsetsSourceControl[] prepareControls() {
- final InsetsSourceControl navBar = new InsetsSourceControl(ITYPE_NAVIGATION_BAR, mLeash,
- new Point());
- final InsetsSourceControl statusBar = new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash,
- new Point());
- final InsetsSourceControl ime = new InsetsSourceControl(ITYPE_IME, mLeash, new Point());
+ final InsetsSourceControl navBar = createControl(ITYPE_NAVIGATION_BAR);
+ final InsetsSourceControl statusBar = createControl(ITYPE_STATUS_BAR);
+ final InsetsSourceControl ime = createControl(ITYPE_IME);
InsetsSourceControl[] controls = new InsetsSourceControl[3];
controls[0] = navBar;
diff --git a/data/etc/car/com.google.android.car.kitchensink.xml b/data/etc/car/com.google.android.car.kitchensink.xml
index 61281ee..efe658a 100644
--- a/data/etc/car/com.google.android.car.kitchensink.xml
+++ b/data/etc/car/com.google.android.car.kitchensink.xml
@@ -33,6 +33,7 @@
<permission name="android.permission.MODIFY_AUDIO_ROUTING"/>
<permission name="android.permission.MODIFY_DAY_NIGHT_MODE"/>
<permission name="android.permission.MODIFY_PHONE_STATE"/>
+ <permission name="android.permission.MONITOR_INPUT"/>
<permission name="android.permission.PROVIDE_TRUST_AGENT"/>
<permission name="android.permission.OVERRIDE_WIFI_CONFIG"/>
<permission name="android.permission.REAL_GET_TASKS"/>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 49edcf7..487a6e9 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -164,6 +164,7 @@
<permission name="android.permission.REBOOT"/>
<permission name="android.permission.REGISTER_CALL_PROVIDER"/>
<permission name="android.permission.REGISTER_SIM_SUBSCRIPTION"/>
+ <permission name="android.permission.REGISTER_STATS_PULL_ATOM"/>
<permission name="android.permission.SEND_RESPOND_VIA_MESSAGE"/>
<permission name="android.permission.SET_TIME_ZONE"/>
<permission name="android.permission.SHUTDOWN"/>
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index d9d2eea..a7d0cb8 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -764,8 +764,9 @@
private @KeyProperties.BlockModeEnum String[] mBlockModes;
private boolean mRandomizedEncryptionRequired = true;
private boolean mUserAuthenticationRequired;
- private int mUserAuthenticationValidityDurationSeconds = -1;
- private @KeyProperties.AuthEnum int mUserAuthenticationType;
+ private int mUserAuthenticationValidityDurationSeconds = 0;
+ private @KeyProperties.AuthEnum int mUserAuthenticationType =
+ KeyProperties.AUTH_BIOMETRIC_STRONG;
private boolean mUserPresenceRequired = false;
private byte[] mAttestationChallenge = null;
private boolean mUniqueIdIncluded = false;
@@ -1240,7 +1241,8 @@
if (seconds == -1) {
return setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG);
}
- return setUserAuthenticationParameters(seconds, KeyProperties.AUTH_BIOMETRIC_STRONG);
+ return setUserAuthenticationParameters(seconds, KeyProperties.AUTH_DEVICE_CREDENTIAL
+ | KeyProperties.AUTH_BIOMETRIC_STRONG);
}
/**
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 8120a93..2e793de 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -562,8 +562,9 @@
private @KeyProperties.BlockModeEnum String[] mBlockModes;
private boolean mRandomizedEncryptionRequired = true;
private boolean mUserAuthenticationRequired;
- private @KeyProperties.AuthEnum int mUserAuthenticationType;
- private int mUserAuthenticationValidityDurationSeconds = -1;
+ private int mUserAuthenticationValidityDurationSeconds = 0;
+ private @KeyProperties.AuthEnum int mUserAuthenticationType =
+ KeyProperties.AUTH_BIOMETRIC_STRONG;
private boolean mUserPresenceRequired = false;
private boolean mUserAuthenticationValidWhileOnBody;
private boolean mInvalidatedByBiometricEnrollment = true;
@@ -870,7 +871,8 @@
if (seconds == -1) {
return setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG);
}
- return setUserAuthenticationParameters(seconds, KeyProperties.AUTH_BIOMETRIC_STRONG);
+ return setUserAuthenticationParameters(seconds, KeyProperties.AUTH_DEVICE_CREDENTIAL
+ | KeyProperties.AUTH_BIOMETRIC_STRONG);
}
/**
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
index 4ead253..bc933ff 100644
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ b/keystore/java/android/security/keystore/KeymasterUtils.java
@@ -165,8 +165,7 @@
}
args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
KeymasterArguments.toUint64(sid));
- args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
- KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_BIOMETRIC);
+ args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, spec.getUserAuthenticationType());
args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
spec.getUserAuthenticationValidityDurationSeconds());
if (spec.isUserAuthenticationValidWhileOnBody()) {
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 550e41f..ff7049e 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -612,7 +612,7 @@
public Location getLastLocation() {
try {
return mService.getLastLocation(null, mContext.getPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -645,7 +645,7 @@
try {
return mService.getLastLocation(request, mContext.getPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -742,7 +742,7 @@
try {
if (mService.getCurrentLocation(currentLocationRequest, remoteCancellationSignal,
- listenerTransport, mContext.getPackageName(), mContext.getFeatureId(),
+ listenerTransport, mContext.getPackageName(), mContext.getAttributionTag(),
getListenerIdentifier(consumer))) {
listenerTransport.register(mContext.getSystemService(AlarmManager.class),
remoteCancellationSignal);
@@ -1189,7 +1189,7 @@
boolean registered = false;
try {
mService.requestLocationUpdates(locationRequest, transport, null,
- mContext.getPackageName(), mContext.getFeatureId(),
+ mContext.getPackageName(), mContext.getAttributionTag(),
getListenerIdentifier(listener));
registered = true;
} catch (RemoteException e) {
@@ -1235,7 +1235,7 @@
try {
mService.requestLocationUpdates(locationRequest, null, pendingIntent,
- mContext.getPackageName(), mContext.getFeatureId(),
+ mContext.getPackageName(), mContext.getAttributionTag(),
getListenerIdentifier(pendingIntent));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1711,7 +1711,7 @@
LocationRequest request = new LocationRequest().setExpireIn(expiration);
try {
mService.requestGeofence(request, fence, intent, mContext.getPackageName(),
- mContext.getFeatureId(), getListenerIdentifier(intent));
+ mContext.getAttributionTag(), getListenerIdentifier(intent));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1798,7 +1798,7 @@
try {
mService.requestGeofence(request, fence, intent, mContext.getPackageName(),
- mContext.getFeatureId(), getListenerIdentifier(intent));
+ mContext.getAttributionTag(), getListenerIdentifier(intent));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2946,7 +2946,7 @@
GnssStatusListener transport = new GnssStatusListener();
if (mService.registerGnssStatusCallback(transport, mContext.getPackageName(),
- mContext.getFeatureId())) {
+ mContext.getAttributionTag())) {
mListenerTransport = transport;
return true;
} else {
@@ -3012,7 +3012,7 @@
GnssMeasurementsListener transport = new GnssMeasurementsListener();
if (mService.addGnssMeasurementsListener(request, transport, mContext.getPackageName(),
- mContext.getFeatureId(), "gnss measurement callback")) {
+ mContext.getAttributionTag(), "gnss measurement callback")) {
mListenerTransport = transport;
return true;
} else {
@@ -3065,7 +3065,7 @@
GnssNavigationMessageListener transport = new GnssNavigationMessageListener();
if (mService.addGnssNavigationMessageListener(transport, mContext.getPackageName(),
- mContext.getFeatureId(), "gnss navigation callback")) {
+ mContext.getAttributionTag(), "gnss navigation callback")) {
mListenerTransport = transport;
return true;
} else {
@@ -3106,7 +3106,7 @@
GnssAntennaInfoListener transport = new GnssAntennaInfoListener();
if (mService.addGnssAntennaInfoListener(transport, mContext.getPackageName(),
- mContext.getFeatureId(), "gnss antenna info callback")) {
+ mContext.getAttributionTag(), "gnss antenna info callback")) {
mListenerTransport = transport;
return true;
} else {
@@ -3143,7 +3143,7 @@
BatchedLocationCallback transport = new BatchedLocationCallback();
if (mService.addGnssBatchingCallback(transport, mContext.getPackageName(),
- mContext.getFeatureId(), "batched location callback")) {
+ mContext.getAttributionTag(), "batched location callback")) {
mListenerTransport = transport;
return true;
} else {
diff --git a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
index dbd9db4..37a016e 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java
@@ -69,7 +69,7 @@
*/
public static final int PLAYBACK_STATUS_FULL = Constants.PlaybackStatus.SPACE_FULL;
- long mNativeContext;
+ private long mNativeContext;
private native int nativeAttachFilter(Filter filter);
private native int nativeDetachFilter(Filter filter);
diff --git a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
index c1c6c62..d06356c 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
@@ -30,7 +30,7 @@
*/
@SystemApi
public class DvrRecorder implements AutoCloseable {
- long mNativeContext;
+ private long mNativeContext;
private native int nativeAttachFilter(Filter filter);
private native int nativeDetachFilter(Filter filter);
diff --git a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
index e99fd36f..1510b2d 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java
@@ -125,9 +125,9 @@
/** @hide */
@IntDef(flag = true,
prefix = "CONSTELLATION_",
- value = {CONSTELLATION_UNDEFINED, CONSTELLATION_AUTO, CONSTELLATION_CONSTELLATION_QPSK,
- CONSTELLATION_CONSTELLATION_16QAM, CONSTELLATION_CONSTELLATION_64QAM,
- CONSTELLATION_CONSTELLATION_256QAM})
+ value = {CONSTELLATION_UNDEFINED, CONSTELLATION_AUTO, CONSTELLATION_QPSK,
+ CONSTELLATION_16QAM, CONSTELLATION_64QAM,
+ CONSTELLATION_256QAM})
@Retention(RetentionPolicy.SOURCE)
public @interface Constellation {}
@@ -142,22 +142,22 @@
/**
* QPSK Constellation.
*/
- public static final int CONSTELLATION_CONSTELLATION_QPSK =
+ public static final int CONSTELLATION_QPSK =
Constants.FrontendDvbtConstellation.CONSTELLATION_QPSK;
/**
* 16QAM Constellation.
*/
- public static final int CONSTELLATION_CONSTELLATION_16QAM =
+ public static final int CONSTELLATION_16QAM =
Constants.FrontendDvbtConstellation.CONSTELLATION_16QAM;
/**
* 64QAM Constellation.
*/
- public static final int CONSTELLATION_CONSTELLATION_64QAM =
+ public static final int CONSTELLATION_64QAM =
Constants.FrontendDvbtConstellation.CONSTELLATION_64QAM;
/**
* 256QAM Constellation.
*/
- public static final int CONSTELLATION_CONSTELLATION_256QAM =
+ public static final int CONSTELLATION_256QAM =
Constants.FrontendDvbtConstellation.CONSTELLATION_256QAM;
@@ -275,11 +275,11 @@
@IntDef(flag = true,
prefix = "GUARD_INTERVAL_",
value = {GUARD_INTERVAL_UNDEFINED, GUARD_INTERVAL_AUTO,
- GUARD_INTERVAL_INTERVAL_1_32, GUARD_INTERVAL_INTERVAL_1_16,
- GUARD_INTERVAL_INTERVAL_1_8, GUARD_INTERVAL_INTERVAL_1_4,
- GUARD_INTERVAL_INTERVAL_1_128,
- GUARD_INTERVAL_INTERVAL_19_128,
- GUARD_INTERVAL_INTERVAL_19_256})
+ GUARD_INTERVAL_1_32, GUARD_INTERVAL_1_16,
+ GUARD_INTERVAL_1_8, GUARD_INTERVAL_1_4,
+ GUARD_INTERVAL_1_128,
+ GUARD_INTERVAL_19_128,
+ GUARD_INTERVAL_19_256})
@Retention(RetentionPolicy.SOURCE)
public @interface GuardInterval {}
@@ -295,37 +295,37 @@
/**
* 1/32 Guard Interval.
*/
- public static final int GUARD_INTERVAL_INTERVAL_1_32 =
+ public static final int GUARD_INTERVAL_1_32 =
Constants.FrontendDvbtGuardInterval.INTERVAL_1_32;
/**
* 1/16 Guard Interval.
*/
- public static final int GUARD_INTERVAL_INTERVAL_1_16 =
+ public static final int GUARD_INTERVAL_1_16 =
Constants.FrontendDvbtGuardInterval.INTERVAL_1_16;
/**
* 1/8 Guard Interval.
*/
- public static final int GUARD_INTERVAL_INTERVAL_1_8 =
+ public static final int GUARD_INTERVAL_1_8 =
Constants.FrontendDvbtGuardInterval.INTERVAL_1_8;
/**
* 1/4 Guard Interval.
*/
- public static final int GUARD_INTERVAL_INTERVAL_1_4 =
+ public static final int GUARD_INTERVAL_1_4 =
Constants.FrontendDvbtGuardInterval.INTERVAL_1_4;
/**
* 1/128 Guard Interval.
*/
- public static final int GUARD_INTERVAL_INTERVAL_1_128 =
+ public static final int GUARD_INTERVAL_1_128 =
Constants.FrontendDvbtGuardInterval.INTERVAL_1_128;
/**
* 19/128 Guard Interval.
*/
- public static final int GUARD_INTERVAL_INTERVAL_19_128 =
+ public static final int GUARD_INTERVAL_19_128 =
Constants.FrontendDvbtGuardInterval.INTERVAL_19_128;
/**
* 19/256 Guard Interval.
*/
- public static final int GUARD_INTERVAL_INTERVAL_19_256 =
+ public static final int GUARD_INTERVAL_19_256 =
Constants.FrontendDvbtGuardInterval.INTERVAL_19_256;
/** @hide */
@@ -435,14 +435,14 @@
* Gets Code Rate for High Priority level.
*/
@CodeRate
- public int getHpCodeRate() {
+ public int getHighPriorityCodeRate() {
return mHpCodeRate;
}
/**
* Gets Code Rate for Low Priority level.
*/
@CodeRate
- public int getLpCodeRate() {
+ public int getLowPriorityCodeRate() {
return mLpCodeRate;
}
/**
@@ -560,7 +560,7 @@
* Sets Code Rate for High Priority level.
*/
@NonNull
- public Builder setHpCodeRate(@CodeRate int hpCodeRate) {
+ public Builder setHighPriorityCodeRate(@CodeRate int hpCodeRate) {
mHpCodeRate = hpCodeRate;
return this;
}
@@ -568,7 +568,7 @@
* Sets Code Rate for Low Priority level.
*/
@NonNull
- public Builder setLpCodeRate(@CodeRate int lpCodeRate) {
+ public Builder setLowPriorityCodeRate(@CodeRate int lpCodeRate) {
mLpCodeRate = lpCodeRate;
return this;
}
diff --git a/media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl b/media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
index 20efaa1..77cac6e 100644
--- a/media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
@@ -19,6 +19,8 @@
import android.media.tv.tunerresourcemanager.CasSessionRequest;
import android.media.tv.tunerresourcemanager.IResourcesReclaimListener;
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
+import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
+import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
@@ -148,6 +150,53 @@
void shareFrontend(in int selfClientId, in int targetClientId);
/*
+ * This API is used by the Tuner framework to request an available demux from the TunerHAL.
+ *
+ * <p>There are three possible scenarios:
+ * <ul>
+ * <li>If there is demux available, the API would send the handle back.
+ *
+ * <li>If no Demux is available but the current request info can show higher priority than
+ * other uses of demuxes, the API will send
+ * {@link IResourcesReclaimListener#onReclaimResources()} to the {@link Tuner}. Tuner would
+ * handle the resource reclaim on the holder of lower priority and notify the holder of its
+ * resource loss.
+ *
+ * <li>If no demux can be granted, the API would return false.
+ * <ul>
+ *
+ * @param request {@link TunerDemuxRequest} information of the current request.
+ * @param demuxHandle a one-element array to return the granted demux handle.
+ *
+ * @return true if there is demux granted.
+ */
+ boolean requestDemux(in TunerDemuxRequest request, out int[] demuxHandle);
+
+ /*
+ * This API is used by the Tuner framework to request an available descrambler from the
+ * TunerHAL.
+ *
+ * <p>There are three possible scenarios:
+ * <ul>
+ * <li>If there is descrambler available, the API would send the handle back.
+ *
+ * <li>If no Descrambler is available but the current request info can show higher priority than
+ * other uses of Descrambler, the API will send
+ * {@link IResourcesReclaimListener#onReclaimResources()} to the {@link Tuner}. Tuner would
+ * handle the resource reclaim on the holder of lower priority and notify the holder of its
+ * resource loss.
+ *
+ * <li>If no Descrambler can be granted, the API would return false.
+ * <ul>
+ *
+ * @param request {@link TunerDescramblerRequest} information of the current request.
+ * @param descramblerHandle a one-element array to return the granted descrambler handle.
+ *
+ * @return true if there is Descrambler granted.
+ */
+ boolean requestDescrambler(in TunerDescramblerRequest request, out int[] descramblerHandle);
+
+ /*
* This API is used by the Tuner framework to request an available Cas session. This session
* needs to be under the CAS system with the id indicated in the {@code request}.
*
@@ -210,6 +259,24 @@
void releaseFrontend(in int frontendId);
/*
+ * Notifies the TRM that the Demux with the given handle was released.
+ *
+ * <p>Client must call this whenever it releases a demux.
+ *
+ * @param demuxHandle the handle of the released Tuner Demux.
+ */
+ void releaseDemux(in int demuxHandle);
+
+ /*
+ * Notifies the TRM that the Descrambler with the given handle was released.
+ *
+ * <p>Client must call this whenever it releases a descrambler.
+ *
+ * @param demuxHandle the handle of the released Tuner Descrambler.
+ */
+ void releaseDescrambler(in int descramblerHandle);
+
+ /*
* Notifies the TRM that the given Cas session has been released.
*
* <p>Client must call this whenever it releases a Cas session.
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl
new file mode 100644
index 0000000..919a215
--- /dev/null
+++ b/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl
@@ -0,0 +1,24 @@
+/*
+ * 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.media.tv.tunerresourcemanager;
+
+/**
+ * Information required to request a Tuner Demux.
+ *
+ * @hide
+ */
+parcelable TunerDemuxRequest;
\ No newline at end of file
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.java b/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.java
new file mode 100644
index 0000000..34a7761
--- /dev/null
+++ b/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.media.tv.tunerresourcemanager;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * Information required to request a Tuner Demux.
+ *
+ * @hide
+ */
+public final class TunerDemuxRequest implements Parcelable {
+ static final String TAG = "TunerDemuxRequest";
+
+ public static final
+ @NonNull
+ Parcelable.Creator<TunerDemuxRequest> CREATOR =
+ new Parcelable.Creator<TunerDemuxRequest>() {
+ @Override
+ public TunerDemuxRequest createFromParcel(Parcel source) {
+ try {
+ return new TunerDemuxRequest(source);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception creating TunerDemuxRequest from parcel", e);
+ return null;
+ }
+ }
+
+ @Override
+ public TunerDemuxRequest[] newArray(int size) {
+ return new TunerDemuxRequest[size];
+ }
+ };
+
+ /**
+ * Client id of the client that sends the request.
+ */
+ private final int mClientId;
+
+ private TunerDemuxRequest(@NonNull Parcel source) {
+ mClientId = source.readInt();
+ }
+
+ /**
+ * Constructs a new {@link TunerDemuxRequest} with the given parameters.
+ *
+ * @param clientId id of the client.
+ */
+ public TunerDemuxRequest(int clientId) {
+ mClientId = clientId;
+ }
+
+ /**
+ * Returns the id of the client.
+ */
+ public int getClientId() {
+ return mClientId;
+ }
+
+ // Parcelable
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ StringBuilder b = new StringBuilder(128);
+ b.append("TunerDemuxRequest {clientId=").append(mClientId);
+ b.append("}");
+ return b.toString();
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mClientId);
+ }
+}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl
new file mode 100644
index 0000000..fbafb3b
--- /dev/null
+++ b/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl
@@ -0,0 +1,24 @@
+/*
+ * 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.media.tv.tunerresourcemanager;
+
+/**
+ * Information required to request a Tuner Descrambler.
+ *
+ * @hide
+ */
+parcelable TunerDescramblerRequest;
\ No newline at end of file
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.java b/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.java
new file mode 100644
index 0000000..5816287
--- /dev/null
+++ b/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.media.tv.tunerresourcemanager;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * Information required to request a Tuner Descrambler.
+ *
+ * @hide
+ */
+public final class TunerDescramblerRequest implements Parcelable {
+ static final String TAG = "TunerDescramblerRequest";
+
+ public static final
+ @NonNull
+ Parcelable.Creator<TunerDescramblerRequest> CREATOR =
+ new Parcelable.Creator<TunerDescramblerRequest>() {
+ @Override
+ public TunerDescramblerRequest createFromParcel(Parcel source) {
+ try {
+ return new TunerDescramblerRequest(source);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception creating TunerDescramblerRequest from parcel", e);
+ return null;
+ }
+ }
+
+ @Override
+ public TunerDescramblerRequest[] newArray(int size) {
+ return new TunerDescramblerRequest[size];
+ }
+ };
+
+ /**
+ * Client id of the client that sends the request.
+ */
+ private final int mClientId;
+
+ private TunerDescramblerRequest(@NonNull Parcel source) {
+ mClientId = source.readInt();
+ }
+
+ /**
+ * Constructs a new {@link TunerDescramblerRequest} with the given parameters.
+ *
+ * @param clientId id of the client.
+ */
+ public TunerDescramblerRequest(int clientId) {
+ mClientId = clientId;
+ }
+
+ /**
+ * Returns the id of the client.
+ */
+ public int getClientId() {
+ return mClientId;
+ }
+
+ // Parcelable
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ StringBuilder b = new StringBuilder(128);
+ b.append("TunerDescramblerRequest {clientId=").append(mClientId);
+ b.append("}");
+ return b.toString();
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mClientId);
+ }
+}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
index 7c11ed4..524b6c2 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
+++ b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
@@ -65,6 +65,7 @@
public static final int INVALID_LNB_ID = -1;
public static final int INVALID_TV_INPUT_DEVICE_ID = -1;
public static final int INVALID_TV_INPUT_PORT_ID = -1;
+ public static final int INVALID_RESOURCE_HANDLE = -1;
private final ITunerResourceManager mService;
private final int mUserId;
@@ -260,6 +261,71 @@
}
/**
+ * Requests a Tuner Demux resource.
+ *
+ * <p>There are three possible scenarios:
+ * <ul>
+ * <li>If there is Demux available, the API would send the handle back.
+ *
+ * <li>If no Demux is available but the current request has a higher priority than other uses of
+ * demuxes, the API will send {@link IResourcesReclaimListener#onReclaimResources()} to the
+ * {@link Tuner}. Tuner would handle the resource reclaim on the holder of lower priority and
+ * notify the holder of its resource loss.
+ *
+ * <li>If no Demux system can be granted, the API would return false.
+ * <ul>
+ *
+ * @param request {@link TunerDemuxRequest} information of the current request.
+ * @param demuxHandle a one-element array to return the granted Demux handle.
+ * If no Demux granted, this will return {@link #INVALID_RESOURCE_HANDLE}.
+ *
+ * @return true if there is Demux granted.
+ */
+ public boolean requestDemux(@NonNull TunerDemuxRequest request, @NonNull int[] demuxHandle) {
+ boolean result = false;
+ try {
+ result = mService.requestDemux(request, demuxHandle);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ return result;
+ }
+
+ /**
+ * Requests a Tuner Descrambler resource.
+ *
+ * <p>There are three possible scenarios:
+ * <ul>
+ * <li>If there is Descrambler available, the API would send the handle back.
+ *
+ * <li>If no Descrambler is available but the current request has a higher priority than other
+ * uses of descramblers, the API will send
+ * {@link IResourcesReclaimListener#onReclaimResources()} to the {@link Tuner}. Tuner would
+ * handle the resource reclaim on the holder of lower priority and notify the holder of its
+ * resource loss.
+ *
+ * <li>If no Descrambler system can be granted, the API would return false.
+ * <ul>
+ *
+ * @param request {@link TunerDescramblerRequest} information of the current request.
+ * @param descramblerHandle a one-element array to return the granted Descrambler handle.
+ * If no Descrambler granted, this will return
+ * {@link #INVALID_RESOURCE_HANDLE}.
+ *
+ * @return true if there is Descrambler granted.
+ */
+ public boolean requestDescrambler(@NonNull TunerDescramblerRequest request,
+ @NonNull int[] descramblerHandle) {
+ boolean result = false;
+ try {
+ result = mService.requestDescrambler(request, descramblerHandle);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ return result;
+ }
+
+ /**
* Requests a CAS session resource.
*
* <p>There are three possible scenarios:
@@ -345,6 +411,36 @@
}
/**
+ * Notifies the TRM that the Demux with the given handle has been released.
+ *
+ * <p>Client must call this whenever it releases an Demux.
+ *
+ * @param demuxHandle the handle of the released Tuner Demux.
+ */
+ public void releaseDemux(int demuxHandle) {
+ try {
+ mService.releaseDemux(demuxHandle);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Notifies the TRM that the Descrambler with the given handle has been released.
+ *
+ * <p>Client must call this whenever it releases an Descrambler.
+ *
+ * @param descramblerHandle the handle of the released Tuner Descrambler.
+ */
+ public void releaseDescrambler(int descramblerHandle) {
+ try {
+ mService.releaseDescrambler(descramblerHandle);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Notifies the TRM that the given Cas session has been released.
*
* <p>Client must call this whenever it releases a Cas session.
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 679f18a..a37c9e5 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -138,11 +138,13 @@
jfieldID filterContext;
jfieldID timeFilterContext;
jfieldID descramblerContext;
- jfieldID dvrContext;
+ jfieldID dvrRecorderContext;
+ jfieldID dvrPlaybackContext;
jmethodID frontendInitID;
jmethodID filterInitID;
jmethodID timeFilterInitID;
- jmethodID dvrInitID;
+ jmethodID dvrRecorderInitID;
+ jmethodID dvrPlaybackInitID;
jmethodID onFrontendEventID;
jmethodID onFilterStatusID;
jmethodID onFilterEventID;
@@ -1333,7 +1335,7 @@
return timeFilterObj;
}
-jobject JTuner::openDvr(DvrType type, int bufferSize) {
+jobject JTuner::openDvr(DvrType type, jlong bufferSize) {
ALOGD("JTuner::openDvr");
if (mDemux == NULL) {
if (openDemux() != Result::SUCCESS) {
@@ -1342,24 +1344,38 @@
}
sp<IDvr> iDvrSp;
sp<DvrCallback> callback = new DvrCallback();
- mDemux->openDvr(type, bufferSize, callback,
- [&](Result, const sp<IDvr>& dvr) {
+ Result res;
+ mDemux->openDvr(type, (uint32_t) bufferSize, callback,
+ [&](Result r, const sp<IDvr>& dvr) {
+ res = r;
iDvrSp = dvr;
});
- if (iDvrSp == NULL) {
+ if (res != Result::SUCCESS || iDvrSp == NULL) {
return NULL;
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
- jobject dvrObj =
- env->NewObject(
- env->FindClass("android/media/tv/tuner/dvr/Dvr"),
- gFields.dvrInitID,
- mObject);
- sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj);
- dvrSp->incStrong(dvrObj);
- env->SetLongField(dvrObj, gFields.dvrContext, (jlong)dvrSp.get());
+ jobject dvrObj;
+ if (type == DvrType::RECORD) {
+ dvrObj =
+ env->NewObject(
+ env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"),
+ gFields.dvrRecorderInitID,
+ mObject);
+ sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj);
+ dvrSp->incStrong(dvrObj);
+ env->SetLongField(dvrObj, gFields.dvrRecorderContext, (jlong)dvrSp.get());
+ } else {
+ dvrObj =
+ env->NewObject(
+ env->FindClass("android/media/tv/tuner/dvr/DvrPlayback"),
+ gFields.dvrPlaybackInitID,
+ mObject);
+ sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj);
+ dvrSp->incStrong(dvrObj);
+ env->SetLongField(dvrObj, gFields.dvrPlaybackContext, (jlong)dvrSp.get());
+ }
callback->setDvr(dvrObj);
@@ -1883,7 +1899,11 @@
}
static sp<Dvr> getDvr(JNIEnv *env, jobject dvr) {
- return (Dvr *)env->GetLongField(dvr, gFields.dvrContext);
+ bool isRecorder =
+ env->IsInstanceOf(dvr, env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"));
+ jfieldID fieldId =
+ isRecorder ? gFields.dvrRecorderContext : gFields.dvrPlaybackContext;
+ return (Dvr *)env->GetLongField(dvr, fieldId);
}
static void android_media_tv_Tuner_native_init(JNIEnv *env) {
@@ -1924,9 +1944,13 @@
gFields.descramblerInitID =
env->GetMethodID(descramblerClazz, "<init>", "()V");
- jclass dvrClazz = env->FindClass("android/media/tv/tuner/dvr/Dvr");
- gFields.dvrContext = env->GetFieldID(dvrClazz, "mNativeContext", "J");
- gFields.dvrInitID = env->GetMethodID(dvrClazz, "<init>", "()V");
+ jclass dvrRecorderClazz = env->FindClass("android/media/tv/tuner/dvr/DvrRecorder");
+ gFields.dvrRecorderContext = env->GetFieldID(dvrRecorderClazz, "mNativeContext", "J");
+ gFields.dvrRecorderInitID = env->GetMethodID(dvrRecorderClazz, "<init>", "()V");
+
+ jclass dvrPlaybackClazz = env->FindClass("android/media/tv/tuner/dvr/DvrPlayback");
+ gFields.dvrPlaybackContext = env->GetFieldID(dvrPlaybackClazz, "mNativeContext", "J");
+ gFields.dvrPlaybackInitID = env->GetMethodID(dvrPlaybackClazz, "<init>", "()V");
jclass linearBlockClazz = env->FindClass("android/media/MediaCodec$LinearBlock");
gFields.linearBlockInitID = env->GetMethodID(linearBlockClazz, "<init>", "()V");
@@ -2654,13 +2678,15 @@
}
static jobject android_media_tv_Tuner_open_dvr_recorder(
- JNIEnv* /* env */, jobject /* thiz */, jlong /* bufferSize */) {
- return NULL;
+ JNIEnv* env, jobject thiz, jlong bufferSize) {
+ sp<JTuner> tuner = getTuner(env, thiz);
+ return tuner->openDvr(DvrType::RECORD, bufferSize);
}
static jobject android_media_tv_Tuner_open_dvr_playback(
- JNIEnv* /* env */, jobject /* thiz */, jlong /* bufferSize */) {
- return NULL;
+ JNIEnv* env, jobject thiz, jlong bufferSize) {
+ sp<JTuner> tuner = getTuner(env, thiz);
+ return tuner->openDvr(DvrType::PLAYBACK, bufferSize);
}
static jobject android_media_tv_Tuner_get_demux_caps(JNIEnv*, jobject) {
@@ -2714,11 +2740,13 @@
}
static int android_media_tv_Tuner_start_dvr(JNIEnv *env, jobject dvr) {
+
sp<IDvr> dvrSp = getDvr(env, dvr)->getIDvr();
if (dvrSp == NULL) {
ALOGD("Failed to start dvr: dvr not found");
return false;
}
+
Result result = dvrSp->start();
return (int) result;
}
@@ -2968,7 +2996,7 @@
{ "nativeClose", "()I", (void *)android_media_tv_Tuner_close_descrambler },
};
-static const JNINativeMethod gDvrMethods[] = {
+static const JNINativeMethod gDvrRecorderMethods[] = {
{ "nativeAttachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
(void *)android_media_tv_Tuner_attach_filter },
{ "nativeDetachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
@@ -2980,14 +3008,22 @@
{ "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
{ "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr },
{ "nativeSetFileDescriptor", "(I)V", (void *)android_media_tv_Tuner_dvr_set_fd },
-};
-
-static const JNINativeMethod gDvrRecorderMethods[] = {
{ "nativeWrite", "(J)J", (void *)android_media_tv_Tuner_write_dvr },
{ "nativeWrite", "([BJJ)J", (void *)android_media_tv_Tuner_write_dvr_to_array },
};
static const JNINativeMethod gDvrPlaybackMethods[] = {
+ { "nativeAttachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
+ (void *)android_media_tv_Tuner_attach_filter },
+ { "nativeDetachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
+ (void *)android_media_tv_Tuner_detach_filter },
+ { "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I",
+ (void *)android_media_tv_Tuner_configure_dvr },
+ { "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr },
+ { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr },
+ { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
+ { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr },
+ { "nativeSetFileDescriptor", "(I)V", (void *)android_media_tv_Tuner_dvr_set_fd },
{ "nativeRead", "(J)J", (void *)android_media_tv_Tuner_read_dvr },
{ "nativeRead", "([BJJ)J", (void *)android_media_tv_Tuner_read_dvr_from_array },
};
@@ -3028,13 +3064,6 @@
return false;
}
if (AndroidRuntime::registerNativeMethods(
- env, "android/media/tv/tuner/dvr/Dvr",
- gDvrMethods,
- NELEM(gDvrMethods)) != JNI_OK) {
- ALOGE("Failed to register dvr native methods");
- return false;
- }
- if (AndroidRuntime::registerNativeMethods(
env, "android/media/tv/tuner/dvr/DvrRecorder",
gDvrRecorderMethods,
NELEM(gDvrRecorderMethods)) != JNI_OK) {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 3b8682f..5d2bba6 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -184,7 +184,7 @@
jobject openFilter(DemuxFilterType type, int bufferSize);
jobject openTimeFilter();
jobject openDescrambler();
- jobject openDvr(DvrType type, int bufferSize);
+ jobject openDvr(DvrType type, jlong bufferSize);
protected:
Result openDemux();
diff --git a/media/jni/soundpool/StreamManager.h b/media/jni/soundpool/StreamManager.h
index 15b39f2..30ad220 100644
--- a/media/jni/soundpool/StreamManager.h
+++ b/media/jni/soundpool/StreamManager.h
@@ -70,9 +70,10 @@
static int staticFunction(void *data) {
JavaThread *jt = static_cast<JavaThread *>(data);
jt->mF();
+ jt->mIsClosed = true; // set the flag that we are closed
+ // now before we allow the destructor to execute;
+ // otherwise there may be a use after free.
jt->mPromise.set_value();
- jt->mIsClosed = true; // publicly inform that we are closed
- // after we have accessed all variables.
return 0;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index 6354ccd..ebd7658 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -284,12 +284,12 @@
ICameraDeviceCallbacks dummyCallbacks = new DummyCameraDeviceCallbacks();
String clientPackageName = getContext().getPackageName();
- String clientFeatureId = getContext().getFeatureId();
+ String clientAttributionTag = getContext().getAttributionTag();
ICameraDeviceUser cameraUser =
mUtils.getCameraService().connectDevice(
dummyCallbacks, String.valueOf(cameraId),
- clientPackageName, clientFeatureId,
+ clientPackageName, clientAttributionTag,
ICameraService.USE_CALLING_UID);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 466c5f4..bf3e746 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -238,12 +238,12 @@
ICameraDeviceCallbacks.Stub dummyCallbacks = new DummyCameraDeviceCallbacks();
String clientPackageName = getContext().getPackageName();
- String clientFeatureId = getContext().getFeatureId();
+ String clientAttributionTag = getContext().getAttributionTag();
mMockCb = spy(dummyCallbacks);
mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
- clientPackageName, clientFeatureId, ICameraService.USE_CALLING_UID);
+ clientPackageName, clientAttributionTag, ICameraService.USE_CALLING_UID);
assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 140c075..8292d30 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -24,7 +24,6 @@
import com.android.keyguard.KeyguardViewController;
import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.CarDeviceProvisionedControllerImpl;
-import com.android.systemui.car.CarNotificationInterruptionStateProvider;
import com.android.systemui.dagger.SystemUIRootComponent;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerImpl;
@@ -41,7 +40,6 @@
import com.android.systemui.statusbar.car.CarStatusBar;
import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
@@ -67,10 +65,6 @@
@Module(includes = {DividerModule.class})
abstract class CarSystemUIModule {
- @Binds
- abstract NotificationInterruptionStateProvider bindNotificationInterruptionStateProvider(
- CarNotificationInterruptionStateProvider notificationInterruptionStateProvider);
-
@Singleton
@Provides
@Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java
deleted file mode 100644
index 447e579..0000000
--- a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2018 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.car;
-
-import android.content.Context;
-
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.notification.NotificationFilter;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.policy.BatteryController;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/** Auto-specific implementation of {@link NotificationInterruptionStateProvider}. */
-@Singleton
-public class CarNotificationInterruptionStateProvider extends
- NotificationInterruptionStateProvider {
-
- @Inject
- public CarNotificationInterruptionStateProvider(Context context,
- NotificationFilter filter,
- StatusBarStateController stateController,
- BatteryController batteryController) {
- super(context, filter, stateController, batteryController);
- }
-
- @Override
- public boolean shouldHeadsUp(NotificationEntry entry) {
- // Because space is usually constrained in the auto use-case, there should not be a
- // pinned notification when the shade has been expanded. Ensure this by not pinning any
- // notification if the shade is already opened.
- if (!getPresenter().isPresenterFullyCollapsed()) {
- return false;
- }
-
- return super.shouldHeadsUp(entry);
- }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index b2e2104..411f14d 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -95,13 +95,15 @@
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationAlertingManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.init.NotificationsController;
+import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.interruption.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -249,7 +251,7 @@
RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
NotificationGutsManager notificationGutsManager,
NotificationLogger notificationLogger,
- NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationInterruptStateProvider notificationInterruptStateProvider,
NotificationViewHierarchyManager notificationViewHierarchyManager,
KeyguardViewMediator keyguardViewMediator,
NotificationAlertingManager notificationAlertingManager,
@@ -335,7 +337,7 @@
remoteInputQuickSettingsDisabler,
notificationGutsManager,
notificationLogger,
- notificationInterruptionStateProvider,
+ notificationInterruptStateProvider,
notificationViewHierarchyManager,
keyguardViewMediator,
notificationAlertingManager,
@@ -488,6 +490,22 @@
.isCurrentUserSetupInProgress();
}
});
+
+ mNotificationInterruptStateProvider.addSuppressor(new NotificationInterruptSuppressor() {
+ @Override
+ public String getName() {
+ return TAG;
+ }
+
+ @Override
+ public boolean suppressInterruptions(NotificationEntry entry) {
+ // Because space is usually constrained in the auto use-case, there should not be a
+ // pinned notification when the shade has been expanded.
+ // Ensure this by not allowing any interruptions (ie: pinning any notifications) if
+ // the shade is already opened.
+ return !getPresenter().isPresenterFullyCollapsed();
+ }
+ });
}
@Override
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
index 4754118..160268b 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
@@ -62,13 +62,13 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.dagger.StatusBarDependenciesModule;
-import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationAlertingManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.init.NotificationsController;
+import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.interruption.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.NotificationRowModule;
@@ -146,7 +146,7 @@
RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
NotificationGutsManager notificationGutsManager,
NotificationLogger notificationLogger,
- NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationInterruptStateProvider notificationInterruptionStateProvider,
NotificationViewHierarchyManager notificationViewHierarchyManager,
KeyguardViewMediator keyguardViewMediator,
NotificationAlertingManager notificationAlertingManager,
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
index f93faeb..ace50f3 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
@@ -545,7 +545,7 @@
bundle.putString(META_DATA_PREFERENCE_KEYHINT, key);
}
try {
- return provider.call(context.getPackageName(), context.getFeatureId(),
+ return provider.call(context.getPackageName(), context.getAttributionTag(),
uri.getAuthority(), method, uri.toString(), bundle);
} catch (RemoteException e) {
return null;
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index e8e1d0b..00f6bcb 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 people with colorblindness see more accurate colors</string>
+ <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>
<!-- 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/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
index 68a3729..245b7843 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAccessesTest.java
@@ -8,7 +8,6 @@
import android.app.AppOpsManager;
import android.app.AppOpsManager.OpEntry;
-import android.app.AppOpsManager.OpFeatureEntry;
import android.app.AppOpsManager.PackageOps;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -163,6 +162,6 @@
AppOpsManager.OP_FLAG_SELF), new AppOpsManager.NoteOpEvent(time, -1, null));
return new OpEntry(op, AppOpsManager.MODE_ALLOWED, Collections.singletonMap(null,
- new OpFeatureEntry(op, false, accessEvents, null)));
+ new AppOpsManager.AttributedOpEntry(op, false, accessEvents, null)));
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
index 3f8d758..cc9b931 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
@@ -7,7 +7,7 @@
import android.app.AppOpsManager;
import android.app.AppOpsManager.OpEntry;
-import android.app.AppOpsManager.OpFeatureEntry;
+import android.app.AppOpsManager.AttributedOpEntry;
import android.app.AppOpsManager.PackageOps;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -18,8 +18,6 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.util.LongSparseArray;
-import android.util.LongSparseLongArray;
-import android.util.Pair;
import org.junit.Before;
import org.junit.Test;
@@ -164,6 +162,6 @@
AppOpsManager.OP_FLAG_SELF), new AppOpsManager.NoteOpEvent(time, duration, null));
return new OpEntry(op, AppOpsManager.MODE_ALLOWED, Collections.singletonMap(null,
- new OpFeatureEntry(op, false, accessEvents, null)));
+ new AttributedOpEntry(op, false, accessEvents, null)));
}
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 8fa98c8..d350d9d 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -141,6 +141,8 @@
Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL,
Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK,
Settings.Secure.UI_NIGHT_MODE,
+ Settings.Secure.DARK_THEME_CUSTOM_START_TIME,
+ Settings.Secure.DARK_THEME_CUSTOM_END_TIME,
Settings.Secure.LOCK_SCREEN_WHEN_TRUST_LOST,
Settings.Secure.SKIP_DIRECTION,
Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 75c5f95..4d33b62 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -28,6 +28,7 @@
import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR;
+import static android.provider.settings.validators.SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.TILE_LIST_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.TTS_LIST_VALIDATOR;
@@ -235,7 +236,9 @@
VALIDATORS.put(Secure.AWARE_TAP_PAUSE_TOUCH_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR);
VALIDATORS.put(Secure.ODI_CAPTIONS_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DARK_MODE_DIALOG_SEEN, BOOLEAN_VALIDATOR);
- VALIDATORS.put(Secure.UI_NIGHT_MODE, new InclusiveIntegerRangeValidator(0, 2));
+ VALIDATORS.put(Secure.UI_NIGHT_MODE, NON_NEGATIVE_INTEGER_VALIDATOR);
+ VALIDATORS.put(Secure.DARK_THEME_CUSTOM_START_TIME, NONE_NEGATIVE_LONG_VALIDATOR);
+ VALIDATORS.put(Secure.DARK_THEME_CUSTOM_END_TIME, NONE_NEGATIVE_LONG_VALIDATOR);
VALIDATORS.put(Secure.GLOBAL_ACTIONS_PANEL_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.AWARE_LOCK_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DISPLAY_DENSITY_FORCED, NON_NEGATIVE_INTEGER_VALIDATOR);
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
index 71c7544..8d5c6e6 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java
@@ -207,4 +207,15 @@
static final Validator ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR =
new AccessibilityShortcutTargetListValidator();
+
+ static final Validator NONE_NEGATIVE_LONG_VALIDATOR = new Validator() {
+ @Override
+ public boolean validate(String value) {
+ try {
+ return Long.parseLong(value) >= 0;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+ };
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 36bb8ef..b6e31d2 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -75,6 +75,9 @@
sBroadcastOnRestore.add(Settings.Secure.ENABLED_VR_LISTENERS);
sBroadcastOnRestore.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
sBroadcastOnRestore.add(Settings.Global.BLUETOOTH_ON);
+ sBroadcastOnRestore.add(Settings.Secure.UI_NIGHT_MODE);
+ sBroadcastOnRestore.add(Settings.Secure.DARK_THEME_CUSTOM_START_TIME);
+ sBroadcastOnRestore.add(Settings.Secure.DARK_THEME_CUSTOM_END_TIME);
}
private interface SettingsLookup {
diff --git a/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java b/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java
index bb9e6f6..9134d87 100644
--- a/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java
@@ -277,6 +277,27 @@
}
@Test
+ public void testPositiveLongValidator_zero() {
+ assertTrue(SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR.validate("0"));
+ }
+
+ @Test
+ public void testPositiveLongValidator_negative() {
+ assertFalse(SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR.validate("-5"));
+ }
+
+
+ @Test
+ public void testPositiveLongValidator_positive() {
+ assertTrue(SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR.validate("5"));
+ }
+
+ @Test
+ public void testPositiveLongValidator_floatFormat() {
+ assertFalse(SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR.validate("4.4756"));
+ }
+
+ @Test
public void testTTSListValidator_withNullInput_returnsFalse() {
assertFalse(SettingsValidators.TTS_LIST_VALIDATOR.validate(null));
}
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index cff958f..c036b04 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -12,6 +12,9 @@
"include-annotation": "android.platform.test.scenario.annotation.Scenario"
},
{
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
@@ -28,6 +31,9 @@
"include-annotation": "android.platform.test.scenario.annotation.Scenario"
},
{
+ "exclude-annotation": "org.junit.Ignore"
+ },
+ {
"exclude-annotation": "androidx.test.filters.FlakyTest"
},
{
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 18fec29..3543073 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2631,10 +2631,7 @@
<string name="controls_favorite_default_title">Controls</string>
<!-- Controls management controls screen subtitle [CHAR LIMIT=NONE] -->
<string name="controls_favorite_subtitle">Choose controls for quick access</string>
- <!-- Controls management controls screen favorites header [CHAR LIMIT=50] -->
- <string name="controls_favorite_header_favorites">Favorites</string>
- <!-- Controls management controls screen all header [CHAR LIMIT=50] -->
- <string name="controls_favorite_header_all">All</string>
+
<!-- Controls management controls screen error on load message [CHAR LIMIT=60] -->
<string name="controls_favorite_load_error">The list of all controls could not be loaded.</string>
<!-- Controls management controls screen header for Other zone [CHAR LIMIT=60] -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WallpaperManagerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WallpaperManagerCompat.java
index b813e21..7570c2c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WallpaperManagerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WallpaperManagerCompat.java
@@ -18,7 +18,11 @@
import android.app.WallpaperManager;
import android.content.Context;
+import android.os.IBinder;
+/**
+ * @see WallpaperManager
+ */
public class WallpaperManagerCompat {
private final WallpaperManager mWallpaperManager;
@@ -26,7 +30,10 @@
mWallpaperManager = context.getSystemService(WallpaperManager.class);
}
- public void setWallpaperZoomOut(float zoom) {
- mWallpaperManager.setWallpaperZoomOut(zoom);
+ /**
+ * @see WallpaperManager#setWallpaperZoomOut(IBinder, float)
+ */
+ public void setWallpaperZoomOut(IBinder windowToken, float zoom) {
+ mWallpaperManager.setWallpaperZoomOut(windowToken, zoom);
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 4508fc7..431c451 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -379,7 +379,7 @@
if (DEBUG_SIM_STATES) {
Log.v(TAG, "onSubscriptionInfoChanged()");
List<SubscriptionInfo> sil = mSubscriptionManager
- .getActiveAndHiddenSubscriptionInfoList();
+ .getCompleteActiveSubscriptionInfoList();
if (sil != null) {
for (SubscriptionInfo subInfo : sil) {
Log.v(TAG, "SubInfo:" + subInfo);
@@ -433,10 +433,10 @@
public List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) {
List<SubscriptionInfo> sil = mSubscriptionInfo;
if (sil == null || forceReload) {
- sil = mSubscriptionManager.getActiveAndHiddenSubscriptionInfoList();
+ sil = mSubscriptionManager.getCompleteActiveSubscriptionInfoList();
}
if (sil == null) {
- // getActiveAndHiddenSubscriptionInfoList was null callers expect an empty list.
+ // getCompleteActiveSubscriptionInfoList was null callers expect an empty list.
mSubscriptionInfo = new ArrayList<SubscriptionInfo>();
} else {
mSubscriptionInfo = sil;
@@ -1086,7 +1086,7 @@
mHandler.sendEmptyMessage(MSG_TIME_UPDATE);
} else if (Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
final Message msg = mHandler.obtainMessage(
- MSG_TIMEZONE_UPDATE, intent.getStringExtra("time-zone"));
+ MSG_TIMEZONE_UPDATE, intent.getStringExtra(Intent.EXTRA_TIMEZONE));
mHandler.sendMessage(msg);
} else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index a868cf5..b6152da 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -71,12 +71,11 @@
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.NotificationFilter;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.interruption.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
@@ -289,7 +288,6 @@
@Inject Lazy<NotificationLogger> mNotificationLogger;
@Inject Lazy<NotificationViewHierarchyManager> mNotificationViewHierarchyManager;
@Inject Lazy<NotificationFilter> mNotificationFilter;
- @Inject Lazy<NotificationInterruptionStateProvider> mNotificationInterruptionStateProvider;
@Inject Lazy<KeyguardDismissUtil> mKeyguardDismissUtil;
@Inject Lazy<SmartReplyController> mSmartReplyController;
@Inject Lazy<RemoteInputQuickSettingsDisabler> mRemoteInputQuickSettingsDisabler;
@@ -489,8 +487,6 @@
mProviders.put(NotificationViewHierarchyManager.class,
mNotificationViewHierarchyManager::get);
mProviders.put(NotificationFilter.class, mNotificationFilter::get);
- mProviders.put(NotificationInterruptionStateProvider.class,
- mNotificationInterruptionStateProvider::get);
mProviders.put(KeyguardDismissUtil.class, mKeyguardDismissUtil::get);
mProviders.put(SmartReplyController.class, mSmartReplyController::get);
mProviders.put(RemoteInputQuickSettingsDisabler.class,
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index dbcdead..23fa645 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -203,6 +203,11 @@
}
}
+ @Override
+ public boolean shouldZoomOutWallpaper() {
+ return true;
+ }
+
private void waitForBackgroundRendering() {
synchronized (mMonitor) {
try {
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index cab9f18..537a812 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -48,6 +48,7 @@
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.os.Handler;
@@ -725,7 +726,8 @@
private final Rect mBoundingRect = new Rect();
private final Path mBoundingPath = new Path();
// Don't initialize these yet because they may never exist
- private Rect mProtectionRect;
+ private RectF mProtectionRect;
+ private RectF mProtectionRectOrig;
private Path mProtectionPath;
private Path mProtectionPathOrig;
private Rect mTotalBounds = new Rect();
@@ -818,7 +820,11 @@
mProtectionPath = new Path();
}
mProtectionPathOrig.set(protectionPath);
- mProtectionRect = pathBounds;
+ if (mProtectionRectOrig == null) {
+ mProtectionRectOrig = new RectF();
+ mProtectionRect = new RectF();
+ }
+ mProtectionRectOrig.set(pathBounds);
}
void setShowProtection(boolean shouldShow) {
@@ -898,6 +904,7 @@
// Reset the protection path so we don't aggregate rotations
mProtectionPath.set(mProtectionPathOrig);
mProtectionPath.transform(m);
+ m.mapRect(mProtectionRect, mProtectionRectOrig);
}
}
@@ -964,7 +971,8 @@
if (mShowProtection) {
// Make sure that our measured height encompases the protection
mTotalBounds.union(mBoundingRect);
- mTotalBounds.union(mProtectionRect);
+ mTotalBounds.union((int) mProtectionRect.left, (int) mProtectionRect.top,
+ (int) mProtectionRect.right, (int) mProtectionRect.bottom);
setMeasuredDimension(
resolveSizeAndState(mTotalBounds.width(), widthMeasureSpec, 0),
resolveSizeAndState(mTotalBounds.height(), heightMeasureSpec, 0));
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index ae1438e..406e7ce 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -83,11 +83,11 @@
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -169,7 +169,7 @@
// Callback that updates BubbleOverflowActivity on data change.
@Nullable private Runnable mOverflowCallback = null;
- private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+ private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private IStatusBarService mBarService;
// Used for determining view rect for touch interaction
@@ -279,7 +279,7 @@
ShadeController shadeController,
BubbleData data,
ConfigurationController configurationController,
- NotificationInterruptionStateProvider interruptionStateProvider,
+ NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
NotificationGroupManager groupManager,
@@ -304,7 +304,7 @@
BubbleData data,
@Nullable BubbleStackView.SurfaceSynchronizer synchronizer,
ConfigurationController configurationController,
- NotificationInterruptionStateProvider interruptionStateProvider,
+ NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
NotificationGroupManager groupManager,
@@ -316,7 +316,7 @@
dumpManager.registerDumpable(TAG, this);
mContext = context;
mShadeController = shadeController;
- mNotificationInterruptionStateProvider = interruptionStateProvider;
+ mNotificationInterruptStateProvider = interruptionStateProvider;
mNotifUserManager = notifUserManager;
mZenModeController = zenModeController;
mFloatingContentCoordinator = floatingContentCoordinator;
@@ -632,7 +632,7 @@
for (NotificationEntry e :
mNotificationEntryManager.getActiveNotificationsForCurrentUser()) {
if (savedBubbleKeys.contains(e.getKey())
- && mNotificationInterruptionStateProvider.shouldBubbleUp(e)
+ && mNotificationInterruptStateProvider.shouldBubbleUp(e)
&& canLaunchInActivityView(mContext, e)) {
updateBubble(e, /* suppressFlyout= */ true);
}
@@ -894,7 +894,7 @@
boolean wasAdjusted = BubbleExperimentConfig.adjustForExperiments(
mContext, entry, previouslyUserCreated, userBlocked);
- if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)
+ if (mNotificationInterruptStateProvider.shouldBubbleUp(entry)
&& (canLaunchInActivityView(mContext, entry) || wasAdjusted)) {
if (wasAdjusted && !previouslyUserCreated) {
// Gotta treat the auto-bubbled / whitelisted packaged bubbles as usercreated
@@ -910,7 +910,7 @@
boolean wasAdjusted = BubbleExperimentConfig.adjustForExperiments(
mContext, entry, previouslyUserCreated, userBlocked);
- boolean shouldBubble = mNotificationInterruptionStateProvider.shouldBubbleUp(entry)
+ boolean shouldBubble = mNotificationInterruptStateProvider.shouldBubbleUp(entry)
&& (canLaunchInActivityView(mContext, entry) || wasAdjusted);
if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.getKey())) {
// It was previously a bubble but no longer a bubble -- lets remove it
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
index ac97d8a..27c9e98 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
@@ -25,8 +25,8 @@
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -54,7 +54,7 @@
ShadeController shadeController,
BubbleData data,
ConfigurationController configurationController,
- NotificationInterruptionStateProvider interruptionStateProvider,
+ NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
NotificationGroupManager groupManager,
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 fd6e256..c5af436 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
@@ -38,8 +38,9 @@
*
* @param component The [ComponentName] of the service to bind
* @param callback a callback to return the loaded controls to (or an error).
+ * @return a runnable to cancel the load
*/
- fun bindAndLoad(component: ComponentName, callback: LoadCallback)
+ fun bindAndLoad(component: ComponentName, callback: LoadCallback): Runnable
/**
* Request to bind to the given service.
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 8f02c25..f8d4a39 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -31,7 +31,6 @@
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.util.concurrency.DelayableExecutor
import dagger.Lazy
-import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
import javax.inject.Singleton
@@ -47,8 +46,6 @@
private const val TAG = "ControlsBindingControllerImpl"
}
- private val refreshing = AtomicBoolean(false)
-
private var currentUser = UserHandle.of(ActivityManager.getCurrentUser())
override val currentUserId: Int
@@ -56,6 +53,12 @@
private var currentProvider: ControlsProviderLifecycleManager? = null
+ /*
+ * Will track any active subscriber for subscribe/unsubscribe requests coming into
+ * this controller. Only one can be active at any time
+ */
+ private var statefulControlSubscriber: StatefulControlSubscriber? = null
+
private val actionCallbackService = object : IControlsActionCallback.Stub() {
override fun accept(
token: IBinder,
@@ -66,27 +69,6 @@
}
}
- private val subscriberService = object : IControlsSubscriber.Stub() {
- override fun onSubscribe(token: IBinder, subs: IControlsSubscription) {
- backgroundExecutor.execute(OnSubscribeRunnable(token, subs))
- }
-
- override fun onNext(token: IBinder, c: Control) {
- if (!refreshing.get()) {
- Log.d(TAG, "Refresh outside of window for token:$token")
- } else {
- backgroundExecutor.execute(OnNextRunnable(token, c))
- }
- }
- override fun onError(token: IBinder, s: String) {
- backgroundExecutor.execute(OnErrorRunnable(token, s))
- }
-
- override fun onComplete(token: IBinder) {
- backgroundExecutor.execute(OnCompleteRunnable(token))
- }
- }
-
@VisibleForTesting
internal open fun createProviderManager(component: ComponentName):
ControlsProviderLifecycleManager {
@@ -94,43 +76,45 @@
context,
backgroundExecutor,
actionCallbackService,
- subscriberService,
currentUser,
component
)
}
private fun retrieveLifecycleManager(component: ComponentName):
- ControlsProviderLifecycleManager? {
+ ControlsProviderLifecycleManager {
if (currentProvider != null && currentProvider?.componentName != component) {
unbind()
}
- if (currentProvider == null) {
- currentProvider = createProviderManager(component)
- }
+ val provider = currentProvider ?: createProviderManager(component)
+ currentProvider = provider
- return currentProvider
+ return provider
}
override fun bindAndLoad(
component: ComponentName,
callback: ControlsBindingController.LoadCallback
- ) {
- retrieveLifecycleManager(component)?.maybeBindAndLoad(LoadSubscriber(callback))
+ ): Runnable {
+ val subscriber = LoadSubscriber(callback)
+ retrieveLifecycleManager(component).maybeBindAndLoad(subscriber)
+ return subscriber.loadCancel()
}
override fun subscribe(structureInfo: StructureInfo) {
- if (refreshing.compareAndSet(false, true)) {
- val provider = retrieveLifecycleManager(structureInfo.componentName)
- provider?.maybeBindAndSubscribe(structureInfo.controls.map { it.controlId })
- }
+ // 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)
+ statefulControlSubscriber = scs
+ provider.maybeBindAndSubscribe(structureInfo.controls.map { it.controlId }, scs)
}
override fun unsubscribe() {
- if (refreshing.compareAndSet(true, false)) {
- currentProvider?.unsubscribe()
- }
+ statefulControlSubscriber?.cancel()
}
override fun action(
@@ -138,20 +122,24 @@
controlInfo: ControlInfo,
action: ControlAction
) {
- retrieveLifecycleManager(componentName)
- ?.maybeBindAndSendAction(controlInfo.controlId, action)
+ if (statefulControlSubscriber == null) {
+ Log.w(TAG, "No actions can occur outside of an active subscription. Ignoring.")
+ } else {
+ retrieveLifecycleManager(componentName)
+ .maybeBindAndSendAction(controlInfo.controlId, action)
+ }
}
override fun bindService(component: ComponentName) {
- retrieveLifecycleManager(component)?.bindService()
+ retrieveLifecycleManager(component).bindService()
}
override fun changeUser(newUser: UserHandle) {
if (newUser == currentUser) return
+ unsubscribe()
unbind()
-
- refreshing.set(false)
+ currentProvider = null
currentUser = newUser
}
@@ -172,8 +160,8 @@
override fun toString(): String {
return StringBuilder(" ControlsBindingController:\n").apply {
- append(" refreshing=${refreshing.get()}\n")
append(" currentUser=$currentUser\n")
+ append(" StatefulControlSubscriber=$statefulControlSubscriber")
append(" Providers=$currentProvider\n")
}.toString()
}
@@ -208,22 +196,6 @@
) : CallbackRunnable(token) {
override fun doRun() {
callback.accept(list)
- provider?.unbindService()
- }
- }
-
- private inner class OnNextRunnable(
- token: IBinder,
- val control: Control
- ) : CallbackRunnable(token) {
- override fun doRun() {
- if (!refreshing.get()) {
- Log.d(TAG, "onRefresh outside of window from:${provider?.componentName}")
- }
-
- provider?.let {
- lazyController.get().refreshStatus(it.componentName, control)
- }
}
}
@@ -232,33 +204,7 @@
val subscription: IControlsSubscription
) : CallbackRunnable(token) {
override fun doRun() {
- if (!refreshing.get()) {
- Log.d(TAG, "onRefresh outside of window from '${provider?.componentName}'")
- }
- provider?.let {
- it.startSubscription(subscription)
- }
- }
- }
-
- private inner class OnCompleteRunnable(
- token: IBinder
- ) : CallbackRunnable(token) {
- override fun doRun() {
- provider?.let {
- Log.i(TAG, "onComplete receive from '${it.componentName}'")
- }
- }
- }
-
- private inner class OnErrorRunnable(
- token: IBinder,
- val error: String
- ) : CallbackRunnable(token) {
- override fun doRun() {
- provider?.let {
- Log.e(TAG, "onError receive from '${it.componentName}': $error")
- }
+ provider?.startSubscription(subscription)
}
}
@@ -292,8 +238,14 @@
) : IControlsSubscriber.Stub() {
val loadedControls = ArrayList<Control>()
var hasError = false
+ private var _loadCancelInternal: (() -> Unit)? = null
+ fun loadCancel() = Runnable {
+ Log.d(TAG, "Cancel load requested")
+ _loadCancelInternal?.invoke()
+ }
override fun onSubscribe(token: IBinder, subs: IControlsSubscription) {
+ _loadCancelInternal = subs::cancel
backgroundExecutor.execute(OnSubscribeRunnable(token, subs))
}
@@ -302,11 +254,15 @@
}
override fun onError(token: IBinder, s: String) {
hasError = true
+ _loadCancelInternal = {}
+ currentProvider?.cancelLoadTimeout()
backgroundExecutor.execute(OnLoadErrorRunnable(token, s, callback))
}
override fun onComplete(token: IBinder) {
+ _loadCancelInternal = {}
if (!hasError) {
+ currentProvider?.cancelLoadTimeout()
backgroundExecutor.execute(OnLoadRunnable(token, loadedControls, callback))
}
}
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 7eafe2e..9e0d26c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -59,6 +59,11 @@
)
/**
+ * Cancels a pending load call
+ */
+ fun cancelLoad()
+
+ /**
* Request to subscribe for favorited controls per structure
*
* @param structureInfo structure to limit the subscription to
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 e5d36f9..9cb902f 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -72,6 +72,8 @@
private var userChanging: Boolean = true
+ private var loadCanceller: Runnable? = null
+
private var currentUser = UserHandle.of(ActivityManager.getCurrentUser())
override val currentUserId
get() = currentUser.identifier
@@ -213,8 +215,9 @@
if (!confirmAvailability()) {
if (userChanging) {
// Try again later, userChanging should not last forever. If so, we have bigger
- // problems
- executor.executeDelayed(
+ // problems. This will return a runnable that allows to cancel the delayed version,
+ // it will not be able to cancel the load if
+ loadCanceller = executor.executeDelayed(
{ loadForComponent(componentName, dataCallback) },
USER_CHANGE_RETRY_DELAY,
TimeUnit.MILLISECONDS
@@ -224,10 +227,11 @@
}
return
}
- bindingController.bindAndLoad(
+ loadCanceller = bindingController.bindAndLoad(
componentName,
object : ControlsBindingController.LoadCallback {
override fun accept(controls: List<Control>) {
+ loadCanceller = null
executor.execute {
val favoritesForComponentKeys = Favorites
.getControlsForComponent(componentName).map { it.controlId }
@@ -251,12 +255,12 @@
controlsWithFavorite,
favoritesForComponentKeys
)
-
dataCallback.accept(loadData)
}
}
override fun error(message: String) {
+ loadCanceller = null
executor.execute {
val loadData = Favorites.getControlsForComponent(componentName)
.let { controls ->
@@ -269,7 +273,6 @@
true
)
}
-
dataCallback.accept(loadData)
}
}
@@ -277,6 +280,12 @@
)
}
+ override fun cancelLoad() {
+ loadCanceller?.let {
+ executor.execute(it)
+ }
+ }
+
private fun createRemovedStatus(
componentName: ComponentName,
controlInfo: ControlInfo,
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 86e8e83..4918bd7 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -58,7 +58,6 @@
private val context: Context,
private val executor: DelayableExecutor,
private val actionCallbackService: IControlsActionCallback.Stub,
- private val subscriberService: IControlsSubscriber.Stub,
val user: UserHandle,
val componentName: ComponentName
) : IBinder.DeathRecipient {
@@ -157,10 +156,9 @@
load(msg.subscriber)
}
- queue.filter { it is Message.Subscribe }.flatMap { (it as Message.Subscribe).list }.run {
- if (this.isNotEmpty()) {
- subscribe(this)
- }
+ 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
@@ -185,9 +183,9 @@
}
}
- private fun unqueueMessage(message: Message) {
+ private fun unqueueMessageType(type: Int) {
synchronized(queuedMessages) {
- queuedMessages.removeIf { it.type == message.type }
+ queuedMessages.removeIf { it.type == type }
}
}
@@ -219,7 +217,7 @@
* @param subscriber the subscriber that manages coordination for loading controls
*/
fun maybeBindAndLoad(subscriber: IControlsSubscriber.Stub) {
- unqueueMessage(Message.Unbind)
+ 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")
@@ -230,6 +228,11 @@
invokeOrQueue({ load(subscriber) }, Message.Load(subscriber))
}
+ fun cancelLoadTimeout() {
+ onLoadCanceller?.run()
+ onLoadCanceller = null
+ }
+
/**
* Request a subscription to the [Publisher] returned by [ControlsProviderService.publisherFor]
*
@@ -237,16 +240,20 @@
*
* @param controlIds a list of the ids of controls to send status back.
*/
- fun maybeBindAndSubscribe(controlIds: List<String>) {
- invokeOrQueue({ subscribe(controlIds) }, Message.Subscribe(controlIds))
+ fun maybeBindAndSubscribe(controlIds: List<String>, subscriber: IControlsSubscriber) {
+ invokeOrQueue(
+ { subscribe(controlIds, subscriber) },
+ Message.Subscribe(controlIds, subscriber)
+ )
}
- private fun subscribe(controlIds: List<String>) {
+ private fun subscribe(controlIds: List<String>, subscriber: IControlsSubscriber) {
if (DEBUG) {
Log.d(TAG, "subscribe $componentName - $controlIds")
}
- if (!(wrapper?.subscribe(controlIds, subscriberService) ?: false)) {
- queueMessage(Message.Subscribe(controlIds))
+
+ if (!(wrapper?.subscribe(controlIds, subscriber) ?: false)) {
+ queueMessage(Message.Subscribe(controlIds, subscriber))
binderDied()
}
}
@@ -276,10 +283,13 @@
/**
* Starts the subscription to the [ControlsProviderService] and requests status of controls.
*
- * @param subscription the subscriber to use to request controls
+ * @param subscription the subscription to use to request controls
* @see maybeBindAndLoad
*/
fun startSubscription(subscription: IControlsSubscription) {
+ if (DEBUG) {
+ Log.d(TAG, "startSubscription: $subscription")
+ }
synchronized(subscriptions) {
subscriptions.add(subscription)
}
@@ -287,30 +297,26 @@
}
/**
- * Unsubscribe from this service, cancelling all status requests.
+ * Cancels the subscription to the [ControlsProviderService].
+ *
+ * @param subscription the subscription to cancel
+ * @see maybeBindAndLoad
*/
- fun unsubscribe() {
+ fun cancelSubscription(subscription: IControlsSubscription) {
if (DEBUG) {
- Log.d(TAG, "unsubscribe $componentName")
+ Log.d(TAG, "cancelSubscription: $subscription")
}
- unqueueMessage(Message.Subscribe(emptyList())) // Removes all subscribe messages
-
- val subs = synchronized(subscriptions) {
- ArrayList(subscriptions).also {
- subscriptions.clear()
- }
+ synchronized(subscriptions) {
+ subscriptions.remove(subscription)
}
-
- subs.forEach {
- wrapper?.cancel(it)
- }
+ wrapper?.cancel(subscription)
}
/**
* Request bind to the service.
*/
fun bindService() {
- unqueueMessage(Message.Unbind)
+ unqueueMessageType(MSG_UNBIND)
bindService(true)
}
@@ -321,8 +327,16 @@
onLoadCanceller?.run()
onLoadCanceller = null
- // just in case this wasn't called already
- unsubscribe()
+ // be sure to cancel all subscriptions
+ val subs = synchronized(subscriptions) {
+ ArrayList(subscriptions).also {
+ subscriptions.clear()
+ }
+ }
+
+ subs.forEach {
+ wrapper?.cancel(it)
+ }
bindService(false)
}
@@ -346,7 +360,7 @@
object Unbind : Message() {
override val type = MSG_UNBIND
}
- class Subscribe(val list: List<String>) : Message() {
+ class Subscribe(val list: List<String>, val subscriber: IControlsSubscriber) : Message() {
override val type = MSG_SUBSCRIBE
}
class Action(val id: String, val action: ControlAction) : Message() {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/StatefulControlSubscriber.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/StatefulControlSubscriber.kt
new file mode 100644
index 0000000..a371aa6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/StatefulControlSubscriber.kt
@@ -0,0 +1,96 @@
+/*
+ * 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.controls.controller
+
+import android.os.IBinder
+import android.service.controls.Control
+import android.service.controls.IControlsSubscriber
+import android.service.controls.IControlsSubscription
+import android.util.Log
+import com.android.systemui.util.concurrency.DelayableExecutor
+
+/**
+ * A single subscriber, supporting stateful controls for publishers created by
+ * {@link ControlsProviderService#createPublisherFor}. In general, this subscription will remain
+ * active until the SysUi chooses to cancel it.
+ */
+class StatefulControlSubscriber(
+ private val controller: ControlsController,
+ private val provider: ControlsProviderLifecycleManager,
+ private val bgExecutor: DelayableExecutor
+) : IControlsSubscriber.Stub() {
+ private var subscriptionOpen = false
+ private var subscription: IControlsSubscription? = null
+
+ companion object {
+ private const val TAG = "StatefulControlSubscriber"
+ }
+
+ private fun run(token: IBinder, f: () -> Unit) {
+ if (provider.token == token) {
+ bgExecutor.execute { f() }
+ }
+ }
+
+ override fun onSubscribe(token: IBinder, subs: IControlsSubscription) {
+ run(token) {
+ subscriptionOpen = true
+ subscription = subs
+ provider.startSubscription(subs)
+ }
+ }
+
+ override fun onNext(token: IBinder, control: Control) {
+ run(token) {
+ if (!subscriptionOpen) {
+ Log.w(TAG, "Refresh outside of window for token:$token")
+ } else {
+ controller.refreshStatus(provider.componentName, control)
+ }
+ }
+ }
+ override fun onError(token: IBinder, error: String) {
+ run(token) {
+ if (subscriptionOpen) {
+ subscriptionOpen = false
+ Log.e(TAG, "onError receive from '${provider.componentName}': $error")
+ }
+ }
+ }
+
+ override fun onComplete(token: IBinder) {
+ run(token) {
+ if (subscriptionOpen) {
+ subscriptionOpen = false
+ Log.i(TAG, "onComplete receive from '${provider.componentName}'")
+ }
+ }
+ }
+
+ fun cancel() {
+ if (!subscriptionOpen) return
+ bgExecutor.execute {
+ if (subscriptionOpen) {
+ subscriptionOpen = false
+ subscription?.let {
+ provider.cancelSubscription(it)
+ }
+ subscription = null
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index 502354a..f2303e6 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -70,6 +70,7 @@
private lateinit var iconFrame: View
private lateinit var pageIndicator: ManagementPageIndicator
private var mTooltipManager: TooltipManager? = null
+ private lateinit var doneButton: View
private var listOfStructures = emptyList<StructureContainer>()
private lateinit var comparator: Comparator<StructureContainer>
@@ -137,6 +138,7 @@
StructureContainer(it.key, AllModel(it.value, favoriteKeys, emptyZoneString))
}.sortedWith(comparator)
executor.execute {
+ doneButton.isEnabled = true
structurePager.adapter = StructureAdapter(listOfStructures)
if (error) {
statusText.text = resources.getText(R.string.controls_favorite_load_error)
@@ -180,6 +182,7 @@
layoutResource = R.layout.controls_management_favorites
inflate()
}
+
statusText = requireViewById(R.id.status_message)
if (shouldShowTooltip()) {
mTooltipManager = TooltipManager(statusText.context,
@@ -248,15 +251,18 @@
}
}
- requireViewById<Button>(R.id.done).setOnClickListener {
- if (component == null) return@setOnClickListener
- listOfStructures.forEach {
- val favoritesForStorage = it.model.favorites.map { it.build() }
- controller.replaceFavoritesForStructure(StructureInfo(component!!, it.structureName,
- favoritesForStorage))
+ doneButton = requireViewById<Button>(R.id.done).apply {
+ isEnabled = false
+ setOnClickListener {
+ if (component == null) return@setOnClickListener
+ listOfStructures.forEach {
+ val favoritesForStorage = it.model.favorites.map { it.build() }
+ controller.replaceFavoritesForStructure(
+ StructureInfo(component!!, it.structureName, favoritesForStorage)
+ )
+ }
+ finishAffinity()
}
-
- finishAffinity()
}
}
@@ -273,6 +279,7 @@
override fun onDestroy() {
currentUserTracker.stopTracking()
listingController.removeCallback(listingCallback)
+ controller.cancelLoad()
super.onDestroy()
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 6c502d2..3a4b273 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -90,7 +90,7 @@
/** */
@Provides
- public AmbientDisplayConfiguration provideAmbientDispalyConfiguration(Context context) {
+ public AmbientDisplayConfiguration provideAmbientDisplayConfiguration(Context context) {
return new AmbientDisplayConfiguration(context);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 513580f..2e9ce12 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -19,7 +19,6 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.view.Choreographer;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.BootCompleteCache;
@@ -31,22 +30,16 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.Recents;
import com.android.systemui.stackdivider.Divider;
-import com.android.systemui.statusbar.BlurUtils;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NotificationShadeWindowBlurController;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.people.PeopleHubModule;
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
-import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
-import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.ConcurrencyModule;
import com.android.systemui.util.sensors.AsyncSensorManager;
import com.android.systemui.util.time.SystemClock;
@@ -98,21 +91,6 @@
keyguardUpdateMonitor, dumpManager);
}
- @Singleton
- @Provides
- @Nullable
- static NotificationShadeWindowBlurController providesBlurController(BlurUtils blurUtils,
- SysuiStatusBarStateController statusBarStateController,
- DumpManager dumpManager, BiometricUnlockController biometricUnlockController,
- KeyguardStateController keyguardStateController,
- NotificationShadeWindowController notificationShadeWindowController,
- Choreographer choreographer) {
- return blurUtils.supportsBlursOnWindows() ? new NotificationShadeWindowBlurController(
- statusBarStateController, blurUtils, biometricUnlockController,
- keyguardStateController, notificationShadeWindowController, choreographer,
- dumpManager) : null;
- }
-
/** */
@Binds
public abstract NotificationRowBinder bindNotificationRowBinder(
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index c45063a..f6fccc0 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -161,15 +161,8 @@
}
int scrimOpacity = -1;
- if (mPaused || mScreenOff) {
- // If AOD is paused, force the screen black until the
- // sensor reports a new brightness. This ensures that when the screen comes on
- // again, it will only show after the brightness sensor has stabilized,
- // avoiding a potential flicker.
- scrimOpacity = 255;
- } else if (!mScreenOff && mLightSensor == null) {
- // No light sensor but previous state turned the screen black. Make the scrim
- // transparent and below views visible.
+ if (mLightSensor == null) {
+ // No light sensor, scrims are always transparent.
scrimOpacity = 0;
} else if (brightnessReady) {
// Only unblank scrim once brightness is ready.
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 786ad2c..27c81ce 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -1793,7 +1793,7 @@
int alpha = (int) (animatedValue * mScrimAlpha * 255);
mBackgroundDrawable.setAlpha(alpha);
mBlurUtils.applyBlur(mGlobalActionsLayout.getViewRootImpl(),
- mBlurUtils.radiusForRatio(animatedValue));
+ mBlurUtils.blurRadiusOfRatio(animatedValue));
})
.start();
if (mControlsUiController != null) {
@@ -1823,7 +1823,7 @@
int alpha = (int) (animatedValue * mScrimAlpha * 255);
mBackgroundDrawable.setAlpha(alpha);
mBlurUtils.applyBlur(mGlobalActionsLayout.getViewRootImpl(),
- mBlurUtils.radiusForRatio(animatedValue));
+ mBlurUtils.blurRadiusOfRatio(animatedValue));
})
.start();
dismissPanel();
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index 280a248..bbb57bd 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -151,7 +151,7 @@
if (mBlurUtils.supportsBlursOnWindows()) {
background.setAlpha((int) (ScrimController.BUSY_SCRIM_ALPHA * 255));
mBlurUtils.applyBlur(d.getWindow().getDecorView().getViewRootImpl(),
- mBlurUtils.radiusForRatio(1));
+ mBlurUtils.blurRadiusOfRatio(1));
} else {
background.setAlpha((int) (SHUTDOWN_SCRIM_ALPHA * 255));
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
index ae380b7..c281ece 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
@@ -93,7 +93,7 @@
return mIatm.startActivityAsUser(
mContext.getIApplicationThread() /*caller*/,
mContext.getBasePackageName() /*callingPackage*/,
- mContext.getFeatureId() /*callingFeatureId*/,
+ mContext.getAttributionTag() /*callingAttributionTag*/,
intent /*intent*/,
intent.resolveTypeIfNeeded(mContext.getContentResolver()) /*resolvedType*/,
null /*resultTo*/,
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 00b977e..51113ac 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -415,11 +415,16 @@
}
mLastReportedBounds.set(destinationBounds);
try {
+ // If we are animating to fullscreen, then we need to reset the override bounds on the
+ // task to ensure that the task "matches" the parent's bounds
+ Rect taskBounds = direction == TRANSITION_DIRECTION_TO_FULLSCREEN
+ ? null
+ : destinationBounds;
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (direction == TRANSITION_DIRECTION_TO_PIP) {
- wct.scheduleFinishEnterPip(mToken, destinationBounds);
+ wct.scheduleFinishEnterPip(mToken, taskBounds);
} else {
- wct.setBounds(mToken, destinationBounds);
+ wct.setBounds(mToken, taskBounds);
}
wct.setBoundsChangeTransaction(mToken, tx);
mTaskOrganizerController.applyContainerTransaction(wct, null /* ITaskOrganizer */);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAppOpsListener.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAppOpsListener.java
index b09d6e1..7dfd99c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAppOpsListener.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAppOpsListener.java
@@ -44,7 +44,7 @@
try {
// Dismiss the PiP once the user disables the app ops setting for that package
final Pair<ComponentName, Integer> topPipActivityInfo =
- PipUtils.getTopPinnedActivity(mContext, mActivityManager);
+ PipUtils.getTopPipActivity(mContext, mActivityManager);
if (topPipActivityInfo.first != null) {
final ApplicationInfo appInfo = mContext.getPackageManager()
.getApplicationInfoAsUser(packageName, 0, topPipActivityInfo.second);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 1fdf92e..2aac188 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -115,7 +115,7 @@
@Override
public void onActivityUnpinned() {
- final Pair<ComponentName, Integer> topPipActivityInfo = PipUtils.getTopPinnedActivity(
+ final Pair<ComponentName, Integer> topPipActivityInfo = PipUtils.getTopPipActivity(
mContext, mActivityManager);
final ComponentName topActivity = topPipActivityInfo.first;
mMenuController.onActivityUnpinned();
@@ -237,6 +237,12 @@
mTouchHandler.getMotionHelper());
displayController.addDisplayChangingController(mRotationController);
+ // Ensure that we have the display info in case we get calls to update the bounds before the
+ // listener calls back
+ final DisplayInfo displayInfo = new DisplayInfo();
+ context.getDisplay().getDisplayInfo(displayInfo);
+ mPipBoundsHandler.onDisplayInfoChanged(displayInfo);
+
try {
ActivityTaskManager.getTaskOrganizerController().registerTaskOrganizer(
mPipTaskOrganizer, WINDOWING_MODE_PINNED);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
index e57b416..849a62a 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
@@ -231,7 +231,7 @@
*/
private void resolveActiveMediaController(List<MediaController> controllers) {
if (controllers != null) {
- final ComponentName topActivity = PipUtils.getTopPinnedActivity(mContext,
+ final ComponentName topActivity = PipUtils.getTopPipActivity(mContext,
mActivityManager).first;
if (topActivity != null) {
for (int i = 0; i < controllers.size(); i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index fc04f79..2b9b171 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -569,7 +569,7 @@
private void showSettings() {
final Pair<ComponentName, Integer> topPipActivityInfo =
- PipUtils.getTopPinnedActivity(this, ActivityManager.getService());
+ PipUtils.getTopPipActivity(this, ActivityManager.getService());
if (topPipActivityInfo.first != null) {
final UserHandle user = UserHandle.of(topPipActivityInfo.second);
final Intent settingsIntent = new Intent(ACTION_PICTURE_IN_PICTURE_SETTINGS,
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 90db91a..b5fb1a9 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -31,6 +31,7 @@
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
+import android.util.Pair;
import android.util.Size;
import android.view.IPinnedStackController;
import android.view.InputEvent;
@@ -148,8 +149,11 @@
@Override
public void onPipDismiss() {
- MetricsLoggerWrapper.logPictureInPictureDismissByTap(mContext,
- PipUtils.getTopPinnedActivity(mContext, mActivityManager));
+ Pair<ComponentName, Integer> topPipActivity = PipUtils.getTopPipActivity(mContext,
+ mActivityManager);
+ if (topPipActivity.first != null) {
+ MetricsLoggerWrapper.logPictureInPictureDismissByTap(mContext, topPipActivity);
+ }
mMotionHelper.dismissPip();
}
@@ -653,7 +657,7 @@
// Check if the user dragged or flung the PiP offscreen to dismiss it
if (mMotionHelper.shouldDismissPip() || isFlingToBot) {
MetricsLoggerWrapper.logPictureInPictureDismissByDrag(mContext,
- PipUtils.getTopPinnedActivity(mContext, mActivityManager));
+ PipUtils.getTopPipActivity(mContext, mActivityManager));
mMotionHelper.animateDismiss(
vel.x, vel.y,
PipTouchHandler.this::updateDismissFraction /* updateAction */);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java
index 1ed1904..4cfec01 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java
@@ -36,7 +36,7 @@
* @return the ComponentName and user id of the top non-SystemUI activity in the pinned stack.
* The component name may be null if no such activity exists.
*/
- public static Pair<ComponentName, Integer> getTopPinnedActivity(Context context,
+ public static Pair<ComponentName, Integer> getTopPipActivity(Context context,
IActivityManager activityManager) {
try {
final String sysUiPackageName = context.getPackageName();
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index fb68153..ea5ec05 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -148,6 +148,8 @@
* regardless of what has focus.
*/
private boolean mTargetShown = false;
+ private float mTargetPrimaryDim = 0.f;
+ private float mTargetSecondaryDim = 0.f;
// The following are the current (most recent) states set during animation
/** {@code true} if the secondary split has IME focus. */
@@ -186,8 +188,12 @@
@Override
public void onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
boolean imeShouldShow, SurfaceControl.Transaction t) {
+ if (!inSplitMode()) {
+ return;
+ }
+ final boolean splitIsVisible = !mView.isHidden();
mSecondaryHasFocus = getSecondaryHasFocus(displayId);
- mTargetAdjusted = imeShouldShow && mSecondaryHasFocus
+ mTargetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus
&& !mSplitLayout.mDisplayLayout.isLandscape();
mHiddenTop = hiddenTop;
mShownTop = shownTop;
@@ -195,6 +201,10 @@
if (mLastAdjustTop < 0) {
mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop;
}
+ mTargetPrimaryDim = (mSecondaryHasFocus && mTargetShown && splitIsVisible)
+ ? ADJUSTED_NONFOCUS_DIM : 0.f;
+ mTargetSecondaryDim = (!mSecondaryHasFocus && mTargetShown && splitIsVisible)
+ ? ADJUSTED_NONFOCUS_DIM : 0.f;
if (mAnimation != null || (mImeWasShown && imeShouldShow
&& mTargetAdjusted != mAdjusted)) {
// We need to animate adjustment independently of the IME position, so
@@ -202,7 +212,11 @@
// different split's editor has gained focus while the IME is still visible.
startAsyncAnimation();
}
- updateImeAdjustState();
+ if (splitIsVisible) {
+ // If split is hidden, we don't want to trigger any relayouts that would cause the
+ // divider to show again.
+ updateImeAdjustState();
+ }
}
private void updateImeAdjustState() {
@@ -245,7 +259,7 @@
@Override
public void onImePositionChanged(int displayId, int imeTop,
SurfaceControl.Transaction t) {
- if (mAnimation != null) {
+ if (mAnimation != null || !inSplitMode()) {
// Not synchronized with IME anymore, so return.
return;
}
@@ -257,7 +271,7 @@
@Override
public void onImeEndPositioning(int displayId, boolean cancelled,
SurfaceControl.Transaction t) {
- if (mAnimation != null) {
+ if (mAnimation != null || !inSplitMode()) {
// Not synchronized with IME anymore, so return.
return;
}
@@ -273,14 +287,10 @@
mSplitLayout.mAdjustedSecondary);
}
final float invProg = 1.f - progress;
- final float targetPrimaryDim =
- (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f;
- final float targetSecondaryDim =
- (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f;
mView.setResizeDimLayer(t, true /* primary */,
- mLastPrimaryDim * invProg + progress * targetPrimaryDim);
+ mLastPrimaryDim * invProg + progress * mTargetPrimaryDim);
mView.setResizeDimLayer(t, false /* primary */,
- mLastSecondaryDim * invProg + progress * targetSecondaryDim);
+ mLastSecondaryDim * invProg + progress * mTargetSecondaryDim);
}
private void onEnd(boolean cancelled, SurfaceControl.Transaction t) {
@@ -289,10 +299,8 @@
mAdjusted = mTargetAdjusted;
mImeWasShown = mTargetShown;
mLastAdjustTop = mAdjusted ? mShownTop : mHiddenTop;
- mLastPrimaryDim =
- (mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f;
- mLastSecondaryDim =
- (!mSecondaryHasFocus && mTargetShown) ? ADJUSTED_NONFOCUS_DIM : 0.f;
+ mLastPrimaryDim = mTargetPrimaryDim;
+ mLastSecondaryDim = mTargetSecondaryDim;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 477cbb7..4114bb9 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -165,6 +165,10 @@
// The view is removed or in the process of been removed from the system.
private boolean mRemoved;
+ // Whether the surface for this view has been hidden regardless of actual visibility. This is
+ // used interact with keyguard.
+ private boolean mSurfaceHidden = false;
+
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -414,6 +418,10 @@
/** Unlike setVisible, this directly hides the surface without changing view visibility. */
void setHidden(boolean hidden) {
+ if (mSurfaceHidden == hidden) {
+ return;
+ }
+ mSurfaceHidden = hidden;
post(() -> {
final SurfaceControl sc = getWindowSurfaceControl();
if (sc == null) {
@@ -430,6 +438,10 @@
});
}
+ boolean isHidden() {
+ return mSurfaceHidden;
+ }
+
public boolean startDragging(boolean animate, boolean touching) {
cancelFlingAnimation();
if (touching) {
@@ -1071,7 +1083,7 @@
void setResizeDimLayer(Transaction t, boolean primary, float alpha) {
SurfaceControl dim = primary ? mTiles.mPrimaryDim : mTiles.mSecondaryDim;
- if (alpha <= 0.f) {
+ if (alpha <= 0.001f) {
t.hide(dim);
} else {
t.setAlpha(dim, alpha);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
index 34c0860..c523b7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
@@ -50,7 +50,7 @@
/**
* Translates a ratio from 0 to 1 to a blur radius in pixels.
*/
- fun radiusForRatio(ratio: Float): Int {
+ fun blurRadiusOfRatio(ratio: Float): Int {
if (ratio == 0f) {
return 0
}
@@ -58,6 +58,17 @@
}
/**
+ * Translates a blur radius in pixels to a ratio between 0 to 1.
+ */
+ fun ratioOfBlurRadius(blur: Int): Float {
+ if (blur == 0) {
+ return 0f
+ }
+ return MathUtils.map(minBlurRadius.toFloat(), maxBlurRadius.toFloat(),
+ 0f /* maxStart */, 1f /* maxStop */, blur.toFloat())
+ }
+
+ /**
* Applies background blurs to a {@link ViewRootImpl}.
*
* @param viewRootImpl The window root.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowBlurController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
similarity index 83%
rename from packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowBlurController.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 6e905a3..901ed3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowBlurController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -19,6 +19,7 @@
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
+import android.app.WallpaperManager
import android.view.Choreographer
import android.view.View
import androidx.dynamicanimation.animation.FloatPropertyCompat
@@ -30,7 +31,6 @@
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK
-import com.android.systemui.statusbar.phone.NotificationShadeWindowController
import com.android.systemui.statusbar.phone.PanelExpansionListener
import com.android.systemui.statusbar.policy.KeyguardStateController
import java.io.FileDescriptor
@@ -43,13 +43,13 @@
* Controller responsible for statusbar window blur.
*/
@Singleton
-class NotificationShadeWindowBlurController @Inject constructor(
+class NotificationShadeDepthController @Inject constructor(
private val statusBarStateController: SysuiStatusBarStateController,
private val blurUtils: BlurUtils,
private val biometricUnlockController: BiometricUnlockController,
private val keyguardStateController: KeyguardStateController,
- private val notificationShadeWindowController: NotificationShadeWindowController,
private val choreographer: Choreographer,
+ private val wallpaperManager: WallpaperManager,
dumpManager: DumpManager
) : PanelExpansionListener, Dumpable {
companion object {
@@ -63,12 +63,12 @@
private var updateScheduled: Boolean = false
private var shadeExpansion = 1.0f
private val shadeSpring = SpringAnimation(this, object :
- FloatPropertyCompat<NotificationShadeWindowBlurController>("shadeBlurRadius") {
- override fun setValue(rect: NotificationShadeWindowBlurController?, value: Float) {
+ FloatPropertyCompat<NotificationShadeDepthController>("shadeBlurRadius") {
+ override fun setValue(rect: NotificationShadeDepthController?, value: Float) {
shadeBlurRadius = value.toInt()
}
- override fun getValue(rect: NotificationShadeWindowBlurController?): Float {
+ override fun getValue(rect: NotificationShadeDepthController?): Float {
return shadeBlurRadius.toFloat()
}
})
@@ -84,12 +84,6 @@
field = value
scheduleUpdate()
}
- private var incomingNotificationBlurRadius = 0
- set(value) {
- if (field == value) return
- field = value
- scheduleUpdate()
- }
/**
* Callback that updates the window blur value and is called only once per frame.
@@ -97,13 +91,9 @@
private val updateBlurCallback = Choreographer.FrameCallback {
updateScheduled = false
- var notificationBlur = 0
- if (statusBarStateController.state == StatusBarState.KEYGUARD) {
- notificationBlur = (incomingNotificationBlurRadius * shadeExpansion).toInt()
- }
-
- val blur = max(max(shadeBlurRadius, wakeAndUnlockBlurRadius), notificationBlur)
+ val blur = max(shadeBlurRadius, wakeAndUnlockBlurRadius)
blurUtils.applyBlur(root.viewRootImpl, blur)
+ wallpaperManager.setWallpaperZoomOut(root.windowToken, blurUtils.ratioOfBlurRadius(blur))
}
/**
@@ -123,7 +113,7 @@
interpolator = Interpolators.DECELERATE_QUINT
addUpdateListener { animation: ValueAnimator ->
wakeAndUnlockBlurRadius =
- blurUtils.radiusForRatio(animation.animatedValue as Float)
+ blurUtils.blurRadiusOfRatio(animation.animatedValue as Float)
}
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator?) {
@@ -163,7 +153,7 @@
var newBlur = 0
if (statusBarStateController.state == StatusBarState.SHADE) {
- newBlur = blurUtils.radiusForRatio(expansion)
+ newBlur = blurUtils.blurRadiusOfRatio(expansion)
}
if (shadeBlurRadius == newBlur) {
@@ -181,11 +171,11 @@
}
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
- IndentingPrintWriter(pw, " ").use {
+ IndentingPrintWriter(pw, " ").let {
it.println("StatusBarWindowBlurController:")
it.increaseIndent()
it.println("shadeBlurRadius: $shadeBlurRadius")
it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius")
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index 8a23e37..2747696 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.notification
import android.animation.ObjectAnimator
-import android.content.Context
import android.util.FloatProperty
import com.android.systemui.Interpolators
import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -26,10 +25,10 @@
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import com.android.systemui.statusbar.phone.DozeParameters
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.NotificationIconAreaController
import com.android.systemui.statusbar.phone.PanelExpansionListener
+import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener
import javax.inject.Inject
@@ -37,15 +36,14 @@
@Singleton
class NotificationWakeUpCoordinator @Inject constructor(
- private val mHeadsUpManagerPhone: HeadsUpManagerPhone,
- private val statusBarStateController: StatusBarStateController,
- private val bypassController: KeyguardBypassController,
- private val dozeParameters: DozeParameters)
- : OnHeadsUpChangedListener, StatusBarStateController.StateListener,
- PanelExpansionListener {
+ private val mHeadsUpManager: HeadsUpManager,
+ private val statusBarStateController: StatusBarStateController,
+ private val bypassController: KeyguardBypassController,
+ private val dozeParameters: DozeParameters
+) : OnHeadsUpChangedListener, StatusBarStateController.StateListener, PanelExpansionListener {
- private val mNotificationVisibility
- = object : FloatProperty<NotificationWakeUpCoordinator>("notificationVisibility") {
+ private val mNotificationVisibility = object : FloatProperty<NotificationWakeUpCoordinator>(
+ "notificationVisibility") {
override fun setValue(coordinator: NotificationWakeUpCoordinator, value: Float) {
coordinator.setVisibilityAmount(value)
@@ -78,10 +76,10 @@
field = value
willWakeUp = false
if (value) {
- if (mNotificationsVisible && !mNotificationsVisibleForExpansion
- && !bypassController.bypassEnabled) {
+ if (mNotificationsVisible && !mNotificationsVisibleForExpansion &&
+ !bypassController.bypassEnabled) {
// We're waking up while pulsing, let's make sure the animation looks nice
- mStackScroller.wakeUpFromPulse();
+ mStackScroller.wakeUpFromPulse()
}
if (bypassController.bypassEnabled && !mNotificationsVisible) {
// Let's make sure our huns become visible once we are waking up in case
@@ -100,7 +98,7 @@
}
private var collapsedEnoughToHide: Boolean = false
- lateinit var iconAreaController : NotificationIconAreaController
+ lateinit var iconAreaController: NotificationIconAreaController
var pulsing: Boolean = false
set(value) {
@@ -132,8 +130,8 @@
var canShow = pulsing
if (bypassController.bypassEnabled) {
// We also allow pulsing on the lock screen!
- canShow = canShow || (wakingUp || willWakeUp || fullyAwake)
- && statusBarStateController.state == StatusBarState.KEYGUARD
+ canShow = canShow || (wakingUp || willWakeUp || fullyAwake) &&
+ statusBarStateController.state == StatusBarState.KEYGUARD
// We want to hide the notifications when collapsed too much
if (collapsedEnoughToHide) {
canShow = false
@@ -143,7 +141,7 @@
}
init {
- mHeadsUpManagerPhone.addListener(this)
+ mHeadsUpManager.addListener(this)
statusBarStateController.addCallback(this)
addListener(object : WakeUpListener {
override fun onFullyHiddenChanged(isFullyHidden: Boolean) {
@@ -155,7 +153,7 @@
increaseSpeed = false)
}
}
- });
+ })
}
fun setStackScroller(stackScroller: NotificationStackScrollLayout) {
@@ -178,46 +176,55 @@
* @param animate should this change be animated
* @param increaseSpeed should the speed be increased of the animation
*/
- fun setNotificationsVisibleForExpansion(visible: Boolean, animate: Boolean,
- increaseSpeed: Boolean) {
+ fun setNotificationsVisibleForExpansion(
+ visible: Boolean,
+ animate: Boolean,
+ increaseSpeed: Boolean
+ ) {
mNotificationsVisibleForExpansion = visible
updateNotificationVisibility(animate, increaseSpeed)
if (!visible && mNotificationsVisible) {
// If we stopped expanding and we're still visible because we had a pulse that hasn't
// times out, let's release them all to make sure were not stuck in a state where
// notifications are visible
- mHeadsUpManagerPhone.releaseAllImmediately()
+ mHeadsUpManager.releaseAllImmediately()
}
}
fun addListener(listener: WakeUpListener) {
- wakeUpListeners.add(listener);
+ wakeUpListeners.add(listener)
}
fun removeListener(listener: WakeUpListener) {
- wakeUpListeners.remove(listener);
+ wakeUpListeners.remove(listener)
}
- private fun updateNotificationVisibility(animate: Boolean, increaseSpeed: Boolean) {
+ private fun updateNotificationVisibility(
+ animate: Boolean,
+ increaseSpeed: Boolean
+ ) {
// TODO: handle Lockscreen wakeup for bypass when we're not pulsing anymore
- var visible = mNotificationsVisibleForExpansion || mHeadsUpManagerPhone.hasNotifications()
+ var visible = mNotificationsVisibleForExpansion || mHeadsUpManager.hasNotifications()
visible = visible && canShowPulsingHuns
if (!visible && mNotificationsVisible && (wakingUp || willWakeUp) && mDozeAmount != 0.0f) {
// let's not make notifications invisible while waking up, otherwise the animation
// is strange
- return;
+ return
}
setNotificationsVisible(visible, animate, increaseSpeed)
}
- private fun setNotificationsVisible(visible: Boolean, animate: Boolean,
- increaseSpeed: Boolean) {
+ private fun setNotificationsVisible(
+ visible: Boolean,
+ animate: Boolean,
+ increaseSpeed: Boolean
+ ) {
if (mNotificationsVisible == visible) {
return
}
mNotificationsVisible = visible
- mVisibilityAnimator?.cancel();
+ mVisibilityAnimator?.cancel()
if (animate) {
notifyAnimationStart(visible)
startVisibilityAnimation(increaseSpeed)
@@ -230,8 +237,8 @@
if (updateDozeAmountIfBypass()) {
return
}
- if (linear != 1.0f && linear != 0.0f
- && (mLinearDozeAmount == 0.0f || mLinearDozeAmount == 1.0f)) {
+ if (linear != 1.0f && linear != 0.0f &&
+ (mLinearDozeAmount == 0.0f || mLinearDozeAmount == 1.0f)) {
// Let's notify the scroller that an animation started
notifyAnimationStart(mLinearDozeAmount == 1.0f)
}
@@ -245,17 +252,17 @@
mStackScroller.setDozeAmount(mDozeAmount)
updateHideAmount()
if (changed && linear == 0.0f) {
- setNotificationsVisible(visible = false, animate = false, increaseSpeed = false);
+ setNotificationsVisible(visible = false, animate = false, increaseSpeed = false)
setNotificationsVisibleForExpansion(visible = false, animate = false,
increaseSpeed = false)
}
}
override fun onStateChanged(newState: Int) {
- updateDozeAmountIfBypass();
+ updateDozeAmountIfBypass()
if (bypassController.bypassEnabled &&
- newState == StatusBarState.KEYGUARD && state == StatusBarState.SHADE_LOCKED
- && (!statusBarStateController.isDozing || shouldAnimateVisibility())) {
+ newState == StatusBarState.KEYGUARD && state == StatusBarState.SHADE_LOCKED &&
+ (!statusBarStateController.isDozing || shouldAnimateVisibility())) {
// We're leaving shade locked. Let's animate the notifications away
setNotificationsVisible(visible = true, increaseSpeed = false, animate = false)
setNotificationsVisible(visible = false, increaseSpeed = false, animate = true)
@@ -266,23 +273,23 @@
override fun onPanelExpansionChanged(expansion: Float, tracking: Boolean) {
val collapsedEnough = expansion <= 0.9f
if (collapsedEnough != this.collapsedEnoughToHide) {
- val couldShowPulsingHuns = canShowPulsingHuns;
+ val couldShowPulsingHuns = canShowPulsingHuns
this.collapsedEnoughToHide = collapsedEnough
if (couldShowPulsingHuns && !canShowPulsingHuns) {
updateNotificationVisibility(animate = true, increaseSpeed = true)
- mHeadsUpManagerPhone.releaseAllImmediately()
+ mHeadsUpManager.releaseAllImmediately()
}
}
}
private fun updateDozeAmountIfBypass(): Boolean {
if (bypassController.bypassEnabled) {
- var amount = 1.0f;
- if (statusBarStateController.state == StatusBarState.SHADE
- || statusBarStateController.state == StatusBarState.SHADE_LOCKED) {
- amount = 0.0f;
+ var amount = 1.0f
+ if (statusBarStateController.state == StatusBarState.SHADE ||
+ statusBarStateController.state == StatusBarState.SHADE_LOCKED) {
+ amount = 0.0f
}
- setDozeAmount(amount, amount)
+ setDozeAmount(amount, amount)
return true
}
return false
@@ -300,7 +307,7 @@
visibilityAnimator.setInterpolator(Interpolators.LINEAR)
var duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP.toLong()
if (increaseSpeed) {
- duration = (duration.toFloat() / 1.5F).toLong();
+ duration = (duration.toFloat() / 1.5F).toLong()
}
visibilityAnimator.setDuration(duration)
visibilityAnimator.start()
@@ -311,7 +318,7 @@
mLinearVisibilityAmount = visibilityAmount
mVisibilityAmount = mVisibilityInterpolator.getInterpolation(
visibilityAmount)
- handleAnimationFinished();
+ handleAnimationFinished()
updateHideAmount()
}
@@ -322,7 +329,7 @@
}
}
- fun getWakeUpHeight() : Float {
+ fun getWakeUpHeight(): Float {
return mStackScroller.wakeUpHeight
}
@@ -330,7 +337,7 @@
val linearAmount = Math.min(1.0f - mLinearVisibilityAmount, mLinearDozeAmount)
val amount = Math.min(1.0f - mVisibilityAmount, mDozeAmount)
mStackScroller.setHideAmount(linearAmount, amount)
- notificationsFullyHidden = linearAmount == 1.0f;
+ notificationsFullyHidden = linearAmount == 1.0f
}
private fun notifyAnimationStart(awake: Boolean) {
@@ -361,7 +368,7 @@
// if we animate, we see the shelf briefly visible. Instead we fully animate
// the notification and its background out
animate = false
- } else if (!wakingUp && !willWakeUp){
+ } else if (!wakingUp && !willWakeUp) {
// TODO: look that this is done properly and not by anyone else
entry.setHeadsUpAnimatingAway(true)
mEntrySetToClearWhenFinished.add(entry)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index e8a62e4..4beeede 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -37,8 +37,8 @@
import com.android.systemui.statusbar.NotificationUiAdjustment;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationClicker;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
import com.android.systemui.statusbar.notification.row.NotifBindPipeline;
@@ -66,7 +66,7 @@
private static final String TAG = "NotificationViewManager";
- private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+ private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private final Context mContext;
private final NotifBindPipeline mNotifBindPipeline;
@@ -97,7 +97,7 @@
StatusBarStateController statusBarStateController,
NotificationGroupManager notificationGroupManager,
NotificationGutsManager notificationGutsManager,
- NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationInterruptStateProvider notificationInterruptionStateProvider,
Provider<RowInflaterTask> rowInflaterTaskProvider,
ExpandableNotificationRowComponent.Builder expandableNotificationRowComponentBuilder) {
mContext = context;
@@ -106,7 +106,7 @@
mMessagingUtil = notificationMessagingUtil;
mNotificationRemoteInputManager = notificationRemoteInputManager;
mNotificationLockscreenUserManager = notificationLockscreenUserManager;
- mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
+ mNotificationInterruptStateProvider = notificationInterruptionStateProvider;
mRowInflaterTaskProvider = rowInflaterTaskProvider;
mExpandableNotificationRowComponentBuilder = expandableNotificationRowComponentBuilder;
}
@@ -243,7 +243,7 @@
params.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp);
params.setUseLowPriority(entry.isAmbient());
- if (mNotificationInterruptionStateProvider.shouldHeadsUp(entry)) {
+ if (mNotificationInterruptStateProvider.shouldHeadsUp(entry)) {
params.requireContentViews(FLAG_CONTENT_VIEW_HEADS_UP);
}
//TODO: Replace this API with RowContentBindParams directly
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index e425ee9..1d8e979 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -31,10 +31,8 @@
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController;
-import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
@@ -44,6 +42,9 @@
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.init.NotificationsControllerImpl;
import com.android.systemui.statusbar.notification.init.NotificationsControllerStub;
+import com.android.systemui.statusbar.notification.interruption.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.logging.NotificationPanelLogger;
import com.android.systemui.statusbar.notification.logging.NotificationPanelLoggerImpl;
@@ -58,6 +59,7 @@
import javax.inject.Singleton;
+import dagger.Binds;
import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
@@ -127,7 +129,7 @@
NotificationRemoteInputManager remoteInputManager,
VisualStabilityManager visualStabilityManager,
StatusBarStateController statusBarStateController,
- NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationInterruptStateProvider notificationInterruptStateProvider,
NotificationListener notificationListener,
HeadsUpManager headsUpManager) {
return new NotificationAlertingManager(
@@ -135,7 +137,7 @@
remoteInputManager,
visualStabilityManager,
statusBarStateController,
- notificationInterruptionStateProvider,
+ notificationInterruptStateProvider,
notificationListener,
headsUpManager);
}
@@ -210,4 +212,9 @@
NotificationEntryManager entryManager) {
return featureFlags.isNewNotifPipelineRenderingEnabled() ? pipeline.get() : entryManager;
}
+
+ /** */
+ @Binds
+ NotificationInterruptStateProvider bindNotificationInterruptStateProvider(
+ NotificationInterruptStateProviderImpl notificationInterruptStateProviderImpl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/BypassHeadsUpNotifier.kt
similarity index 96%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/BypassHeadsUpNotifier.kt
index 269a7a5..88888d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/BypassHeadsUpNotifier.kt
@@ -14,7 +14,7 @@
* limitations under the License
*/
-package com.android.systemui.statusbar.notification
+package com.android.systemui.statusbar.notification.interruption
import android.content.Context
import android.media.MediaMetadata
@@ -24,6 +24,7 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.NotificationMediaManager
import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.NotificationEntryManager
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.phone.KeyguardBypassController
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationAlertingManager.java
similarity index 90%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationAlertingManager.java
index df21f0b..b572502 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationAlertingManager.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification;
+package com.android.systemui.statusbar.notification.interruption;
import static com.android.systemui.statusbar.NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
@@ -27,6 +27,9 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -39,7 +42,7 @@
private final NotificationRemoteInputManager mRemoteInputManager;
private final VisualStabilityManager mVisualStabilityManager;
private final StatusBarStateController mStatusBarStateController;
- private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+ private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private final NotificationListener mNotificationListener;
private HeadsUpManager mHeadsUpManager;
@@ -52,13 +55,13 @@
NotificationRemoteInputManager remoteInputManager,
VisualStabilityManager visualStabilityManager,
StatusBarStateController statusBarStateController,
- NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationInterruptStateProvider notificationInterruptionStateProvider,
NotificationListener notificationListener,
HeadsUpManager headsUpManager) {
mRemoteInputManager = remoteInputManager;
mVisualStabilityManager = visualStabilityManager;
mStatusBarStateController = statusBarStateController;
- mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
+ mNotificationInterruptStateProvider = notificationInterruptionStateProvider;
mNotificationListener = notificationListener;
mHeadsUpManager = headsUpManager;
@@ -94,7 +97,7 @@
if (entry.getRow().getPrivateLayout().getHeadsUpChild() != null) {
// Possible for shouldHeadsUp to change between the inflation starting and ending.
// If it does and we no longer need to heads up, we should free the view.
- if (mNotificationInterruptionStateProvider.shouldHeadsUp(entry)) {
+ if (mNotificationInterruptStateProvider.shouldHeadsUp(entry)) {
mHeadsUpManager.showNotification(entry);
if (!mStatusBarStateController.isDozing()) {
// Mark as seen immediately
@@ -109,7 +112,7 @@
private void updateAlertState(NotificationEntry entry) {
boolean alertAgain = alertAgain(entry, entry.getSbn().getNotification());
// includes check for whether this notification should be filtered:
- boolean shouldAlert = mNotificationInterruptionStateProvider.shouldHeadsUp(entry);
+ boolean shouldAlert = mNotificationInterruptStateProvider.shouldHeadsUp(entry);
final boolean wasAlerting = mHeadsUpManager.isAlerting(entry.getKey());
if (wasAlerting) {
if (shouldAlert) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
new file mode 100644
index 0000000..3292a8f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
@@ -0,0 +1,59 @@
+/*
+ * 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.interruption;
+
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+/**
+ * Provides bubble-up and heads-up state for notification entries.
+ *
+ * When a notification is heads-up when dozing, this is also called "pulsing."
+ */
+public interface NotificationInterruptStateProvider {
+ /**
+ * If the device is awake (not dozing):
+ * Whether the notification should peek in from the top and alert the user.
+ *
+ * If the device is dozing:
+ * Whether the notification should show the ambient view of the notification ("pulse").
+ *
+ * @param entry the entry to check
+ * @return true if the entry should heads up, false otherwise
+ */
+ boolean shouldHeadsUp(NotificationEntry entry);
+
+ /**
+ * Whether the notification should appear as a bubble with a fly-out on top of the screen.
+ *
+ * @param entry the entry to check
+ * @return true if the entry should bubble up, false otherwise
+ */
+ boolean shouldBubbleUp(NotificationEntry entry);
+
+ /**
+ * Whether to launch the entry's full screen intent when the entry is added.
+ *
+ * @param entry the entry that was added
+ * @return {@code true} if we should launch the full screen intent
+ */
+ boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry);
+
+ /**
+ * Add a component that can suppress visual interruptions.
+ */
+ void addSuppressor(NotificationInterruptSuppressor suppressor);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
similarity index 63%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
index bbf2dde..46d5044 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
@@ -14,33 +14,35 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification;
+package com.android.systemui.statusbar.notification.interruption;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
import android.app.NotificationManager;
-import android.content.Context;
+import android.content.ContentResolver;
import android.database.ContentObserver;
import android.hardware.display.AmbientDisplayConfiguration;
+import android.os.Handler;
import android.os.PowerManager;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
-import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import java.util.ArrayList;
+import java.util.List;
+
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -48,120 +50,84 @@
* Provides heads-up and pulsing state for notification entries.
*/
@Singleton
-public class NotificationInterruptionStateProvider {
-
+public class NotificationInterruptStateProviderImpl implements NotificationInterruptStateProvider {
private static final String TAG = "InterruptionStateProvider";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true; //false;
private static final boolean DEBUG_HEADS_UP = true;
private static final boolean ENABLE_HEADS_UP = true;
private static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";
+ private final List<NotificationInterruptSuppressor> mSuppressors = new ArrayList<>();
private final StatusBarStateController mStatusBarStateController;
private final NotificationFilter mNotificationFilter;
- private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
-
- private final Context mContext;
+ private final ContentResolver mContentResolver;
private final PowerManager mPowerManager;
private final IDreamManager mDreamManager;
+ private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
private final BatteryController mBatteryController;
-
- private NotificationPresenter mPresenter;
+ private final ContentObserver mHeadsUpObserver;
private HeadsUpManager mHeadsUpManager;
- private HeadsUpSuppressor mHeadsUpSuppressor;
- private ContentObserver mHeadsUpObserver;
@VisibleForTesting
protected boolean mUseHeadsUp = false;
- private boolean mDisableNotificationAlerts;
@Inject
- public NotificationInterruptionStateProvider(Context context, NotificationFilter filter,
- StatusBarStateController stateController, BatteryController batteryController) {
- this(context,
- (PowerManager) context.getSystemService(Context.POWER_SERVICE),
- IDreamManager.Stub.asInterface(
- ServiceManager.checkService(DreamService.DREAM_SERVICE)),
- new AmbientDisplayConfiguration(context),
- filter,
- batteryController,
- stateController);
- }
-
- @VisibleForTesting
- protected NotificationInterruptionStateProvider(
- Context context,
+ public NotificationInterruptStateProviderImpl(
+ ContentResolver contentResolver,
PowerManager powerManager,
IDreamManager dreamManager,
AmbientDisplayConfiguration ambientDisplayConfiguration,
NotificationFilter notificationFilter,
BatteryController batteryController,
- StatusBarStateController statusBarStateController) {
- mContext = context;
+ StatusBarStateController statusBarStateController,
+ HeadsUpManager headsUpManager,
+ @Main Handler mainHandler) {
+ mContentResolver = contentResolver;
mPowerManager = powerManager;
mDreamManager = dreamManager;
mBatteryController = batteryController;
mAmbientDisplayConfiguration = ambientDisplayConfiguration;
mNotificationFilter = notificationFilter;
mStatusBarStateController = statusBarStateController;
- }
-
- /** Sets up late-binding dependencies for this component. */
- public void setUpWithPresenter(
- NotificationPresenter notificationPresenter,
- HeadsUpManager headsUpManager,
- HeadsUpSuppressor headsUpSuppressor) {
- setUpWithPresenter(notificationPresenter, headsUpManager, headsUpSuppressor,
- new ContentObserver(Dependency.get(Dependency.MAIN_HANDLER)) {
- @Override
- public void onChange(boolean selfChange) {
- boolean wasUsing = mUseHeadsUp;
- mUseHeadsUp = ENABLE_HEADS_UP && !mDisableNotificationAlerts
- && Settings.Global.HEADS_UP_OFF != Settings.Global.getInt(
- mContext.getContentResolver(),
- Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
- Settings.Global.HEADS_UP_OFF);
- Log.d(TAG, "heads up is " + (mUseHeadsUp ? "enabled" : "disabled"));
- if (wasUsing != mUseHeadsUp) {
- if (!mUseHeadsUp) {
- Log.d(TAG,
- "dismissing any existing heads up notification on disable"
- + " event");
- mHeadsUpManager.releaseAllImmediately();
- }
- }
- }
- });
- }
-
- /** Sets up late-binding dependencies for this component. */
- public void setUpWithPresenter(
- NotificationPresenter notificationPresenter,
- HeadsUpManager headsUpManager,
- HeadsUpSuppressor headsUpSuppressor,
- ContentObserver observer) {
- mPresenter = notificationPresenter;
mHeadsUpManager = headsUpManager;
- mHeadsUpSuppressor = headsUpSuppressor;
- mHeadsUpObserver = observer;
+ mHeadsUpObserver = new ContentObserver(mainHandler) {
+ @Override
+ public void onChange(boolean selfChange) {
+ boolean wasUsing = mUseHeadsUp;
+ mUseHeadsUp = ENABLE_HEADS_UP
+ && Settings.Global.HEADS_UP_OFF != Settings.Global.getInt(
+ mContentResolver,
+ Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
+ Settings.Global.HEADS_UP_OFF);
+ Log.d(TAG, "heads up is " + (mUseHeadsUp ? "enabled" : "disabled"));
+ if (wasUsing != mUseHeadsUp) {
+ if (!mUseHeadsUp) {
+ Log.d(TAG, "dismissing any existing heads up notification on "
+ + "disable event");
+ mHeadsUpManager.releaseAllImmediately();
+ }
+ }
+ }
+ };
if (ENABLE_HEADS_UP) {
- mContext.getContentResolver().registerContentObserver(
+ mContentResolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED),
true,
mHeadsUpObserver);
- mContext.getContentResolver().registerContentObserver(
+ mContentResolver.registerContentObserver(
Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true,
mHeadsUpObserver);
}
mHeadsUpObserver.onChange(true); // set up
}
- /**
- * Whether the notification should appear as a bubble with a fly-out on top of the screen.
- *
- * @param entry the entry to check
- * @return true if the entry should bubble up, false otherwise
- */
+ @Override
+ public void addSuppressor(NotificationInterruptSuppressor suppressor) {
+ mSuppressors.add(suppressor);
+ }
+
+ @Override
public boolean shouldBubbleUp(NotificationEntry entry) {
final StatusBarNotification sbn = entry.getSbn();
@@ -201,12 +167,8 @@
return true;
}
- /**
- * Whether the notification should peek in from the top and alert the user.
- *
- * @param entry the entry to check
- * @return true if the entry should heads up, false otherwise
- */
+
+ @Override
public boolean shouldHeadsUp(NotificationEntry entry) {
if (mStatusBarStateController.isDozing()) {
return shouldHeadsUpWhenDozing(entry);
@@ -215,6 +177,17 @@
}
}
+ /**
+ * When an entry was added, should we launch its fullscreen intent? Examples are Alarms or
+ * incoming calls.
+ */
+ @Override
+ public boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry) {
+ return entry.getSbn().getNotification().fullScreenIntent != null
+ && (!shouldHeadsUp(entry)
+ || mStatusBarStateController.getState() == StatusBarState.KEYGUARD);
+ }
+
private boolean shouldHeadsUpWhenAwake(NotificationEntry entry) {
StatusBarNotification sbn = entry.getSbn();
@@ -271,13 +244,15 @@
return false;
}
- if (!mHeadsUpSuppressor.canHeadsUp(entry, sbn)) {
- if (DEBUG_HEADS_UP) {
- Log.d(TAG, "No heads up: aborted by suppressor: " + sbn.getKey());
+ for (int i = 0; i < mSuppressors.size(); i++) {
+ if (mSuppressors.get(i).suppressAwakeHeadsUp(entry)) {
+ if (DEBUG_HEADS_UP) {
+ Log.d(TAG, "No heads up: aborted by suppressor: "
+ + mSuppressors.get(i).getName() + " sbnKey=" + sbn.getKey());
+ }
+ return false;
}
- return false;
}
-
return true;
}
@@ -325,7 +300,7 @@
}
return false;
}
- return true;
+ return true;
}
/**
@@ -334,8 +309,7 @@
* @param entry the entry to check
* @return true if these checks pass, false if the notification should not alert
*/
- @VisibleForTesting
- public boolean canAlertCommon(NotificationEntry entry) {
+ private boolean canAlertCommon(NotificationEntry entry) {
StatusBarNotification sbn = entry.getSbn();
if (mNotificationFilter.shouldFilterOut(entry)) {
@@ -352,6 +326,16 @@
}
return false;
}
+
+ for (int i = 0; i < mSuppressors.size(); i++) {
+ if (mSuppressors.get(i).suppressInterruptions(entry)) {
+ if (DEBUG_HEADS_UP) {
+ Log.d(TAG, "No alerting: aborted by suppressor: "
+ + mSuppressors.get(i).getName() + " sbnKey=" + sbn.getKey());
+ }
+ return false;
+ }
+ }
return true;
}
@@ -361,15 +345,17 @@
* @param entry the entry to check
* @return true if these checks pass, false if the notification should not alert
*/
- @VisibleForTesting
- public boolean canAlertAwakeCommon(NotificationEntry entry) {
+ private boolean canAlertAwakeCommon(NotificationEntry entry) {
StatusBarNotification sbn = entry.getSbn();
- if (mPresenter.isDeviceInVrMode()) {
- if (DEBUG_HEADS_UP) {
- Log.d(TAG, "No alerting: no huns or vr mode");
+ for (int i = 0; i < mSuppressors.size(); i++) {
+ if (mSuppressors.get(i).suppressAwakeInterruptions(entry)) {
+ if (DEBUG_HEADS_UP) {
+ Log.d(TAG, "No alerting: aborted by suppressor: "
+ + mSuppressors.get(i).getName() + " sbnKey=" + sbn.getKey());
+ }
+ return false;
}
- return false;
}
if (isSnoozedPackage(sbn)) {
@@ -392,54 +378,4 @@
private boolean isSnoozedPackage(StatusBarNotification sbn) {
return mHeadsUpManager.isSnoozed(sbn.getPackageName());
}
-
- /** Sets whether to disable all alerts. */
- public void setDisableNotificationAlerts(boolean disableNotificationAlerts) {
- mDisableNotificationAlerts = disableNotificationAlerts;
- mHeadsUpObserver.onChange(true);
- }
-
- /** Whether all alerts are disabled. */
- @VisibleForTesting
- public boolean areNotificationAlertsDisabled() {
- return mDisableNotificationAlerts;
- }
-
- /** Whether HUNs should be used. */
- @VisibleForTesting
- public boolean getUseHeadsUp() {
- return mUseHeadsUp;
- }
-
- protected NotificationPresenter getPresenter() {
- return mPresenter;
- }
-
- /**
- * When an entry was added, should we launch its fullscreen intent? Examples are Alarms or
- * incoming calls.
- *
- * @param entry the entry that was added
- * @return {@code true} if we should launch the full screen intent
- */
- public boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry) {
- return entry.getSbn().getNotification().fullScreenIntent != null
- && (!shouldHeadsUp(entry)
- || mStatusBarStateController.getState() == StatusBarState.KEYGUARD);
- }
-
- /** A component which can suppress heads-up notifications due to the overall state of the UI. */
- public interface HeadsUpSuppressor {
- /**
- * Returns false if the provided notification is ineligible for heads-up according to this
- * component.
- *
- * @param entry entry of the notification that might be heads upped
- * @param sbn notification that might be heads upped
- * @return false if the notification can not be heads upped
- */
- boolean canHeadsUp(NotificationEntry entry, StatusBarNotification sbn);
-
- }
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptSuppressor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptSuppressor.java
new file mode 100644
index 0000000..c19f8bd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptSuppressor.java
@@ -0,0 +1,64 @@
+/*
+ * 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.interruption;
+
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+/** A component which can suppress visual interruptions of notifications such as heads-up and
+ * bubble-up.
+ */
+public interface NotificationInterruptSuppressor {
+ /**
+ * A unique name to identify this suppressor.
+ */
+ default String getName() {
+ return this.getClass().getName();
+ }
+
+ /**
+ * Returns true if the provided notification is, when the device is awake, ineligible for
+ * heads-up according to this component.
+ *
+ * @param entry entry of the notification that might heads-up
+ * @return true if the heads up interruption should be suppressed when the device is awake
+ */
+ default boolean suppressAwakeHeadsUp(NotificationEntry entry) {
+ return false;
+ }
+
+ /**
+ * Returns true if the provided notification is, when the device is awake, ineligible for
+ * heads-up or bubble-up according to this component.
+ *
+ * @param entry entry of the notification that might heads-up or bubble-up
+ * @return true if interruptions should be suppressed when the device is awake
+ */
+ default boolean suppressAwakeInterruptions(NotificationEntry entry) {
+ return false;
+ }
+
+ /**
+ * Returns true if the provided notification is, regardless of awake/dozing state,
+ * ineligible for heads-up or bubble-up according to this component.
+ *
+ * @param entry entry of the notification that might heads-up or bubble-up
+ * @return true if interruptions should be suppressed
+ */
+ default boolean suppressInterruptions(NotificationEntry entry) {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
index 597bdb9..be3873a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
@@ -83,7 +83,7 @@
private val Ranking.personTypeInfo
get() = when {
- channel.isImportantConversation -> TYPE_IMPORTANT_PERSON
+ channel?.isImportantConversation == true -> TYPE_IMPORTANT_PERSON
isConversation -> TYPE_PERSON
else -> TYPE_NON_PERSON
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index ee31300..90bc075b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -492,7 +492,7 @@
try {
result = ActivityTaskManager.getService().startActivityAsUser(
null, getContext().getBasePackageName(),
- getContext().getFeatureId(), intent,
+ getContext().getAttributionTag(), intent,
intent.resolveTypeIfNeeded(getContext().getContentResolver()),
null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, o.toBundle(),
UserHandle.CURRENT.getIdentifier());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
index c5c3fff..c54fa29 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
@@ -27,6 +27,8 @@
*/
public class KeyguardIndicationTextView extends TextView {
+ private CharSequence mText = "";
+
public KeyguardIndicationTextView(Context context) {
super(context);
}
@@ -53,10 +55,12 @@
// TODO: Animation, make sure that we will show one indication long enough.
if (TextUtils.isEmpty(text)) {
+ mText = "";
setVisibility(View.INVISIBLE);
- } else {
+ } else if (!TextUtils.equals(text, mText)) {
+ mText = text;
setVisibility(View.VISIBLE);
- setText(text);
+ setText(mText);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
index f38d416..596a607 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
@@ -18,7 +18,6 @@
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
-import android.annotation.Nullable;
import android.app.StatusBarManager;
import android.graphics.RectF;
import android.hardware.display.AmbientDisplayConfiguration;
@@ -44,7 +43,7 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationShadeWindowBlurController;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -82,7 +81,7 @@
private final CommandQueue mCommandQueue;
private final NotificationShadeWindowView mView;
private final ShadeController mShadeController;
- private final NotificationShadeWindowBlurController mBlurController;
+ private final NotificationShadeDepthController mDepthController;
private GestureDetector mGestureDetector;
private View mBrightnessMirror;
@@ -126,7 +125,7 @@
CommandQueue commandQueue,
ShadeController shadeController,
DockManager dockManager,
- @Nullable NotificationShadeWindowBlurController blurController,
+ NotificationShadeDepthController depthController,
NotificationShadeWindowView notificationShadeWindowView,
NotificationPanelViewController notificationPanelViewController,
SuperStatusBarViewFactory statusBarViewFactory) {
@@ -149,7 +148,7 @@
mShadeController = shadeController;
mDockManager = dockManager;
mNotificationPanelViewController = notificationPanelViewController;
- mBlurController = blurController;
+ mDepthController = depthController;
mStatusBarViewFactory = statusBarViewFactory;
// This view is not part of the newly inflated expanded status bar.
@@ -394,10 +393,8 @@
mView.getContext(), mView, expandHelperCallback,
dragDownCallback, mFalsingManager));
- if (mBlurController != null) {
- mBlurController.setRoot(mView);
- mNotificationPanelViewController.addExpansionListener(mBlurController);
- }
+ mDepthController.setRoot(mView);
+ mNotificationPanelViewController.addExpansionListener(mDepthController);
}
public NotificationShadeWindowView getView() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index b3a62d8..d343090 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -185,15 +185,15 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
-import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
-import com.android.systemui.statusbar.notification.NotificationAlertingManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.init.NotificationsController;
+import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.interruption.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -404,10 +404,9 @@
private final NotificationGutsManager mGutsManager;
private final NotificationLogger mNotificationLogger;
- private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
private final NotificationViewHierarchyManager mViewHierarchyManager;
private final KeyguardViewMediator mKeyguardViewMediator;
- private final NotificationAlertingManager mNotificationAlertingManager;
+ protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
// for disabling the status bar
private int mDisabled1 = 0;
@@ -621,10 +620,10 @@
RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
NotificationGutsManager notificationGutsManager,
NotificationLogger notificationLogger,
- NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationInterruptStateProvider notificationInterruptStateProvider,
NotificationViewHierarchyManager notificationViewHierarchyManager,
KeyguardViewMediator keyguardViewMediator,
- NotificationAlertingManager notificationAlertingManager,
+ NotificationAlertingManager notificationAlertingManager, // need to inject for now
DisplayMetrics displayMetrics,
MetricsLogger metricsLogger,
@UiBackground Executor uiBgExecutor,
@@ -701,10 +700,9 @@
mRemoteInputQuickSettingsDisabler = remoteInputQuickSettingsDisabler;
mGutsManager = notificationGutsManager;
mNotificationLogger = notificationLogger;
- mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
+ mNotificationInterruptStateProvider = notificationInterruptStateProvider;
mViewHierarchyManager = notificationViewHierarchyManager;
mKeyguardViewMediator = keyguardViewMediator;
- mNotificationAlertingManager = notificationAlertingManager;
mDisplayMetrics = displayMetrics;
mMetricsLogger = metricsLogger;
mUiBgExecutor = uiBgExecutor;
@@ -1238,9 +1236,9 @@
mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanelViewController,
mHeadsUpManager, mNotificationShadeWindowView, mStackScroller, mDozeScrimController,
mScrimController, mActivityLaunchAnimator, mDynamicPrivacyController,
- mNotificationAlertingManager, mKeyguardStateController,
- mKeyguardIndicationController,
- this /* statusBar */, mShadeController, mCommandQueue, mInitController);
+ mKeyguardStateController, mKeyguardIndicationController,
+ this /* statusBar */, mShadeController, mCommandQueue, mInitController,
+ mNotificationInterruptStateProvider);
mNotificationShelf.setOnActivatedListener(mPresenter);
mRemoteInputManager.getController().addCallback(mNotificationShadeWindowController);
@@ -1589,8 +1587,9 @@
}
if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) {
- mNotificationInterruptionStateProvider.setDisableNotificationAlerts(
- (state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0);
+ if (areNotificationAlertsDisabled()) {
+ mHeadsUpManager.releaseAllImmediately();
+ }
}
if ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) {
@@ -1605,6 +1604,10 @@
}
}
+ boolean areNotificationAlertsDisabled() {
+ return (mDisabled1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
+ }
+
protected H createHandler() {
return new StatusBar.H();
}
@@ -2599,7 +2602,7 @@
}
try {
result = ActivityTaskManager.getService().startActivityAsUser(
- null, mContext.getBasePackageName(), mContext.getFeatureId(),
+ null, mContext.getBasePackageName(), mContext.getAttributionTag(),
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index e1a20b6..53fa263 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -68,12 +68,12 @@
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
@@ -108,7 +108,7 @@
private final NotifCollection mNotifCollection;
private final FeatureFlags mFeatureFlags;
private final StatusBarStateController mStatusBarStateController;
- private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+ private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private final MetricsLogger mMetricsLogger;
private final Context mContext;
private final NotificationPanelViewController mNotificationPanel;
@@ -142,7 +142,7 @@
NotificationLockscreenUserManager lockscreenUserManager,
ShadeController shadeController, StatusBar statusBar,
KeyguardStateController keyguardStateController,
- NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationInterruptStateProvider notificationInterruptStateProvider,
MetricsLogger metricsLogger, LockPatternUtils lockPatternUtils,
Handler mainThreadHandler, Handler backgroundHandler, Executor uiBgExecutor,
ActivityIntentHelper activityIntentHelper, BubbleController bubbleController,
@@ -167,7 +167,7 @@
mActivityStarter = activityStarter;
mEntryManager = entryManager;
mStatusBarStateController = statusBarStateController;
- mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
+ mNotificationInterruptStateProvider = notificationInterruptStateProvider;
mMetricsLogger = metricsLogger;
mAssistManagerLazy = assistManagerLazy;
mGroupManager = groupManager;
@@ -436,7 +436,7 @@
}
private void handleFullScreenIntent(NotificationEntry entry) {
- if (mNotificationInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) {
+ if (mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) {
if (shouldSuppressFullScreenIntent(entry)) {
if (DEBUG) {
Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + entry.getKey());
@@ -603,7 +603,7 @@
private final ActivityIntentHelper mActivityIntentHelper;
private final BubbleController mBubbleController;
private NotificationPanelViewController mNotificationPanelViewController;
- private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+ private NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private final ShadeController mShadeController;
private NotificationPresenter mNotificationPresenter;
private ActivityLaunchAnimator mActivityLaunchAnimator;
@@ -626,7 +626,7 @@
NotificationGroupManager groupManager,
NotificationLockscreenUserManager lockscreenUserManager,
KeyguardStateController keyguardStateController,
- NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationInterruptStateProvider notificationInterruptStateProvider,
MetricsLogger metricsLogger,
LockPatternUtils lockPatternUtils,
@Main Handler mainThreadHandler,
@@ -654,7 +654,7 @@
mGroupManager = groupManager;
mLockscreenUserManager = lockscreenUserManager;
mKeyguardStateController = keyguardStateController;
- mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
+ mNotificationInterruptStateProvider = notificationInterruptStateProvider;
mMetricsLogger = metricsLogger;
mLockPatternUtils = lockPatternUtils;
mMainThreadHandler = mainThreadHandler;
@@ -712,7 +712,7 @@
mShadeController,
mStatusBar,
mKeyguardStateController,
- mNotificationInterruptionStateProvider,
+ mNotificationInterruptStateProvider,
mMetricsLogger,
mLockPatternUtils,
mMainThreadHandler,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 30d6b507..79cea91 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -60,13 +60,13 @@
import com.android.systemui.statusbar.notification.AboveShelfObserver;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -98,8 +98,6 @@
(SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
private final NotificationEntryManager mEntryManager =
Dependency.get(NotificationEntryManager.class);
- private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider =
- Dependency.get(NotificationInterruptionStateProvider.class);
private final NotificationMediaManager mMediaManager =
Dependency.get(NotificationMediaManager.class);
private final VisualStabilityManager mVisualStabilityManager =
@@ -140,13 +138,13 @@
ScrimController scrimController,
ActivityLaunchAnimator activityLaunchAnimator,
DynamicPrivacyController dynamicPrivacyController,
- NotificationAlertingManager notificationAlertingManager,
KeyguardStateController keyguardStateController,
KeyguardIndicationController keyguardIndicationController,
StatusBar statusBar,
ShadeController shadeController,
CommandQueue commandQueue,
- InitController initController) {
+ InitController initController,
+ NotificationInterruptStateProvider notificationInterruptStateProvider) {
mContext = context;
mKeyguardStateController = keyguardStateController;
mNotificationPanel = panel;
@@ -216,8 +214,7 @@
mEntryManager.addNotificationLifetimeExtender(mGutsManager);
mEntryManager.addNotificationLifetimeExtenders(
remoteInputManager.getLifetimeExtenders());
- mNotificationInterruptionStateProvider.setUpWithPresenter(
- this, mHeadsUpManager, this::canHeadsUp);
+ notificationInterruptStateProvider.addSuppressor(mInterruptSuppressor);
mLockscreenUserManager.setUpWithPresenter(this);
mMediaManager.setUpWithPresenter(this);
mVisualStabilityManager.setUpWithPresenter(this);
@@ -336,39 +333,6 @@
return mEntryManager.hasActiveNotifications();
}
- public boolean canHeadsUp(NotificationEntry entry, StatusBarNotification sbn) {
- if (mStatusBar.isOccluded()) {
- boolean devicePublic = mLockscreenUserManager.
- isLockscreenPublicMode(mLockscreenUserManager.getCurrentUserId());
- boolean userPublic = devicePublic
- || mLockscreenUserManager.isLockscreenPublicMode(sbn.getUserId());
- boolean needsRedaction = mLockscreenUserManager.needsRedaction(entry);
- if (userPublic && needsRedaction) {
- // TODO(b/135046837): we can probably relax this with dynamic privacy
- return false;
- }
- }
-
- if (!mCommandQueue.panelsEnabled()) {
- if (DEBUG) {
- Log.d(TAG, "No heads up: disabled panel : " + sbn.getKey());
- }
- return false;
- }
-
- if (sbn.getNotification().fullScreenIntent != null) {
- if (mAccessibilityManager.isTouchExplorationEnabled()) {
- if (DEBUG) Log.d(TAG, "No heads up: accessible fullscreen: " + sbn.getKey());
- return false;
- } else {
- // we only allow head-up on the lockscreen if it doesn't have a fullscreen intent
- return !mKeyguardStateController.isShowing()
- || mStatusBar.isOccluded();
- }
- }
- return true;
- }
-
@Override
public void onUserSwitched(int newUserId) {
// Begin old BaseStatusBar.userSwitched
@@ -507,4 +471,66 @@
}
}
};
+
+ private final NotificationInterruptSuppressor mInterruptSuppressor =
+ new NotificationInterruptSuppressor() {
+ @Override
+ public String getName() {
+ return TAG;
+ }
+
+ @Override
+ public boolean suppressAwakeHeadsUp(NotificationEntry entry) {
+ final StatusBarNotification sbn = entry.getSbn();
+ if (mStatusBar.isOccluded()) {
+ boolean devicePublic = mLockscreenUserManager
+ .isLockscreenPublicMode(mLockscreenUserManager.getCurrentUserId());
+ boolean userPublic = devicePublic
+ || mLockscreenUserManager.isLockscreenPublicMode(sbn.getUserId());
+ boolean needsRedaction = mLockscreenUserManager.needsRedaction(entry);
+ if (userPublic && needsRedaction) {
+ // TODO(b/135046837): we can probably relax this with dynamic privacy
+ return true;
+ }
+ }
+
+ if (!mCommandQueue.panelsEnabled()) {
+ if (DEBUG) {
+ Log.d(TAG, "No heads up: disabled panel : " + sbn.getKey());
+ }
+ return true;
+ }
+
+ if (sbn.getNotification().fullScreenIntent != null) {
+ // we don't allow head-up on the lockscreen (unless there's a
+ // "showWhenLocked" activity currently showing) if
+ // the potential HUN has a fullscreen intent
+ if (mKeyguardStateController.isShowing() && !mStatusBar.isOccluded()) {
+ if (DEBUG) {
+ Log.d(TAG, "No heads up: entry has fullscreen intent on lockscreen "
+ + sbn.getKey());
+ }
+ return true;
+ }
+
+ if (mAccessibilityManager.isTouchExplorationEnabled()) {
+ if (DEBUG) {
+ Log.d(TAG, "No heads up: accessible fullscreen: " + sbn.getKey());
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean suppressAwakeInterruptions(NotificationEntry entry) {
+ return isDeviceInVrMode();
+ }
+
+ @Override
+ public boolean suppressInterruptions(NotificationEntry entry) {
+ return mStatusBar.areNotificationAlertsDisabled();
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index eec8d50..bbc7e7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -56,13 +56,13 @@
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationAlertingManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.init.NotificationsController;
+import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.interruption.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -139,7 +139,7 @@
RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
NotificationGutsManager notificationGutsManager,
NotificationLogger notificationLogger,
- NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationInterruptStateProvider notificationInterruptStateProvider,
NotificationViewHierarchyManager notificationViewHierarchyManager,
KeyguardViewMediator keyguardViewMediator,
NotificationAlertingManager notificationAlertingManager,
@@ -218,7 +218,7 @@
remoteInputQuickSettingsDisabler,
notificationGutsManager,
notificationLogger,
- notificationInterruptionStateProvider,
+ notificationInterruptStateProvider,
notificationViewHierarchyManager,
keyguardViewMediator,
notificationAlertingManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 759bad4..812ce1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -236,7 +236,7 @@
String action = intent.getAction();
if (action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
- String tz = intent.getStringExtra("time-zone");
+ String tz = intent.getStringExtra(Intent.EXTRA_TIMEZONE);
handler.post(() -> {
mCalendar = Calendar.getInstance(TimeZone.getTimeZone(tz));
if (mClockFormat != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index cebcf76..54e8e72 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -577,7 +577,7 @@
}
boolean isDataDisabled() {
- return !mPhone.isDataConnectionEnabled();
+ return !mPhone.isDataConnectionAllowed();
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index b84208c..99709402 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -630,7 +630,7 @@
@VisibleForTesting
void doUpdateMobileControllers() {
List<SubscriptionInfo> subscriptions = mSubscriptionManager
- .getActiveAndHiddenSubscriptionInfoList();
+ .getCompleteActiveSubscriptionInfoList();
if (subscriptions == null) {
subscriptions = Collections.emptyList();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java
index 73ffe42..e70e30a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/AudioRecordingDisclosureBar.java
@@ -24,6 +24,7 @@
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.annotation.IntDef;
+import android.annotation.UiThread;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -133,6 +134,7 @@
new OnActiveRecordingListener());
}
+ @UiThread
private void onStartedRecording(String packageName) {
if (!mActiveAudioRecordingPackages.add(packageName)) {
// This app is already known to perform recording
@@ -164,6 +166,7 @@
}
}
+ @UiThread
private void onDoneRecording(String packageName) {
if (!mActiveAudioRecordingPackages.remove(packageName)) {
// Was not marked as an active recorder, do nothing
@@ -179,6 +182,7 @@
}
}
+ @UiThread
private void show(String packageName) {
// Inflate the indicator view
mIndicatorView = LayoutInflater.from(mContext).inflate(
@@ -253,6 +257,7 @@
mState = STATE_APPEARING;
}
+ @UiThread
private void expand(String packageName) {
final String label = getApplicationLabel(packageName);
mTextView.setText(mContext.getString(R.string.app_accessed_mic, label));
@@ -276,6 +281,7 @@
mState = STATE_MAXIMIZING;
}
+ @UiThread
private void minimize() {
final int targetOffset = mTextsContainers.getWidth();
final AnimatorSet set = new AnimatorSet();
@@ -297,6 +303,7 @@
mState = STATE_MINIMIZING;
}
+ @UiThread
private void hide() {
final int targetOffset =
mIndicatorView.getWidth() - (int) mIconTextsContainer.getTranslationX();
@@ -317,12 +324,14 @@
mState = STATE_DISAPPEARING;
}
+ @UiThread
private void onExpanded() {
mState = STATE_SHOWN;
mIndicatorView.postDelayed(this::minimize, MAXIMIZED_DURATION);
}
+ @UiThread
private void onMinimized() {
mState = STATE_MINIMIZED;
@@ -336,6 +345,7 @@
}
}
+ @UiThread
private void onHidden() {
final WindowManager windowManager = (WindowManager) mContext.getSystemService(
Context.WINDOW_SERVICE);
@@ -358,6 +368,7 @@
}
}
+ @UiThread
private void startPulsatingAnimation() {
final View pulsatingView = mIconTextsContainer.findViewById(R.id.pulsating_circle);
final ObjectAnimator animator =
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 2452218..248bdc8 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -41,9 +41,9 @@
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.util.leak.LeakDetector;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -69,7 +69,8 @@
// Map of Uris we listen on to their settings keys.
private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>();
// Map of settings keys to the listener.
- private final HashMap<String, Set<Tunable>> mTunableLookup = new HashMap<>();
+ private final ConcurrentHashMap<String, Set<Tunable>> mTunableLookup =
+ new ConcurrentHashMap<>();
// Set of all tunables, used for leak detection.
private final HashSet<Tunable> mTunables = LeakDetector.ENABLED ? new HashSet<>() : null;
private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
index 23df991..ccb8699 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
@@ -324,7 +324,7 @@
@Override
public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
- boolean sync) {}
+ float zoom, boolean sync) {}
@Override
public void dispatchWallpaperCommand(String action, int x, int y,
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index ea6cf33..f7daf97 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -249,7 +249,7 @@
// STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
// same answer as KeyguardUpdateMonitor. Remove when this is addressed
- when(mSubscriptionManager.getActiveAndHiddenSubscriptionInfoList()).thenReturn(
+ when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()).thenReturn(
new ArrayList<>());
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index eead120..4f4ce13 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -516,7 +516,7 @@
List<SubscriptionInfo> list = new ArrayList<>();
list.add(TEST_SUBSCRIPTION);
list.add(TEST_SUBSCRIPTION_2);
- when(mSubscriptionManager.getActiveAndHiddenSubscriptionInfoList()).thenReturn(list);
+ when(mSubscriptionManager.getCompleteActiveSubscriptionInfoList()).thenReturn(list);
mKeyguardUpdateMonitor.mPhoneStateListener.onActiveDataSubscriptionIdChanged(
TEST_SUBSCRIPTION_2.getSubscriptionId());
mTestableLooper.processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 78160c4..6e612d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -45,7 +45,11 @@
import android.app.Notification;
import android.app.PendingIntent;
import android.content.res.Resources;
+import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.face.FaceManager;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.service.dreams.IDreamManager;
import android.service.notification.ZenModeConfig;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -61,14 +65,12 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -227,15 +229,17 @@
mZenModeConfig.suppressedVisualEffects = 0;
when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);
- TestableNotificationInterruptionStateProvider interruptionStateProvider =
- new TestableNotificationInterruptionStateProvider(mContext,
+ TestableNotificationInterruptStateProviderImpl interruptionStateProvider =
+ new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(),
+ mock(PowerManager.class),
+ mock(IDreamManager.class),
+ mock(AmbientDisplayConfiguration.class),
mock(NotificationFilter.class),
mock(StatusBarStateController.class),
- mock(BatteryController.class));
- interruptionStateProvider.setUpWithPresenter(
- mock(NotificationPresenter.class),
- mock(HeadsUpManager.class),
- mock(NotificationInterruptionStateProvider.HeadsUpSuppressor.class));
+ mock(BatteryController.class),
+ mock(HeadsUpManager.class),
+ mock(Handler.class)
+ );
mBubbleData = new BubbleData(mContext);
when(mFeatureFlagsOldPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
mBubbleController = new TestableBubbleController(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index 5ef4cd2..6244644 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -41,7 +41,11 @@
import android.app.Notification;
import android.app.PendingIntent;
import android.content.res.Resources;
+import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.face.FaceManager;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.service.dreams.IDreamManager;
import android.service.notification.ZenModeConfig;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -57,12 +61,10 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
@@ -212,15 +214,17 @@
mZenModeConfig.suppressedVisualEffects = 0;
when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);
- TestableNotificationInterruptionStateProvider interruptionStateProvider =
- new TestableNotificationInterruptionStateProvider(mContext,
+ TestableNotificationInterruptStateProviderImpl interruptionStateProvider =
+ new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(),
+ mock(PowerManager.class),
+ mock(IDreamManager.class),
+ mock(AmbientDisplayConfiguration.class),
mock(NotificationFilter.class),
mock(StatusBarStateController.class),
- mock(BatteryController.class));
- interruptionStateProvider.setUpWithPresenter(
- mock(NotificationPresenter.class),
- mock(HeadsUpManager.class),
- mock(NotificationInterruptionStateProvider.HeadsUpSuppressor.class));
+ mock(BatteryController.class),
+ mock(HeadsUpManager.class),
+ mock(Handler.class)
+ );
mBubbleData = new BubbleData(mContext);
when(mFeatureFlagsNewPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(true);
mBubbleController = new TestableBubbleController(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
index de1fb41..d3d90c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
@@ -23,8 +23,8 @@
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -44,7 +44,7 @@
ShadeController shadeController,
BubbleData data,
ConfigurationController configurationController,
- NotificationInterruptionStateProvider interruptionStateProvider,
+ NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController,
NotificationLockscreenUserManager lockscreenUserManager,
NotificationGroupManager groupManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableNotificationInterruptStateProviderImpl.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableNotificationInterruptStateProviderImpl.java
new file mode 100644
index 0000000..17dc76b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableNotificationInterruptStateProviderImpl.java
@@ -0,0 +1,55 @@
+/*
+ * 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.bubbles;
+
+import android.content.ContentResolver;
+import android.hardware.display.AmbientDisplayConfiguration;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.service.dreams.IDreamManager;
+
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationFilter;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+
+public class TestableNotificationInterruptStateProviderImpl
+ extends NotificationInterruptStateProviderImpl {
+
+ TestableNotificationInterruptStateProviderImpl(
+ ContentResolver contentResolver,
+ PowerManager powerManager,
+ IDreamManager dreamManager,
+ AmbientDisplayConfiguration ambientDisplayConfiguration,
+ NotificationFilter filter,
+ StatusBarStateController statusBarStateController,
+ BatteryController batteryController,
+ HeadsUpManager headsUpManager,
+ Handler mainHandler) {
+ super(contentResolver,
+ powerManager,
+ dreamManager,
+ ambientDisplayConfiguration,
+ filter,
+ batteryController,
+ statusBarStateController,
+ headsUpManager,
+ mainHandler);
+ mUseHeadsUp = true;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableNotificationInterruptionStateProvider.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableNotificationInterruptionStateProvider.java
deleted file mode 100644
index 5d192b2..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableNotificationInterruptionStateProvider.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.bubbles;
-
-import android.content.Context;
-
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.notification.NotificationFilter;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
-import com.android.systemui.statusbar.policy.BatteryController;
-
-public class TestableNotificationInterruptionStateProvider
- extends NotificationInterruptionStateProvider {
-
- TestableNotificationInterruptionStateProvider(Context context,
- NotificationFilter filter, StatusBarStateController controller,
- BatteryController batteryController) {
- super(context, filter, controller, batteryController);
- mUseHeadsUp = true;
- }
-}
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 eceb1dd..c25d4e2 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
@@ -22,6 +22,8 @@
import android.os.UserHandle
import android.service.controls.Control
import android.service.controls.DeviceTypes
+import android.service.controls.IControlsSubscriber
+import android.service.controls.IControlsSubscription
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -34,6 +36,8 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.`when`
@@ -48,6 +52,7 @@
class ControlsBindingControllerImplTest : SysuiTestCase() {
companion object {
+ fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
fun <T> any(): T = Mockito.any<T>()
private val TEST_COMPONENT_NAME_1 = ComponentName("TEST_PKG", "TEST_CLS_1")
private val TEST_COMPONENT_NAME_2 = ComponentName("TEST_PKG", "TEST_CLS_2")
@@ -57,6 +62,15 @@
@Mock
private lateinit var mockControlsController: ControlsController
+ @Captor
+ private lateinit var subscriberCaptor: ArgumentCaptor<IControlsSubscriber.Stub>
+
+ @Captor
+ private lateinit var loadSubscriberCaptor: ArgumentCaptor<IControlsSubscriber.Stub>
+
+ @Captor
+ private lateinit var listStringCaptor: ArgumentCaptor<List<String>>
+
private val user = UserHandle.of(mContext.userId)
private val otherUser = UserHandle.of(user.identifier + 1)
@@ -97,6 +111,102 @@
}
@Test
+ fun testBindAndLoad_cancel() {
+ val callback = object : ControlsBindingController.LoadCallback {
+ override fun error(message: String) {}
+
+ override fun accept(t: List<Control>) {}
+ }
+ val subscription = mock(IControlsSubscription::class.java)
+
+ val canceller = controller.bindAndLoad(TEST_COMPONENT_NAME_1, callback)
+
+ verify(providers[0]).maybeBindAndLoad(capture(loadSubscriberCaptor))
+ loadSubscriberCaptor.value.onSubscribe(Binder(), subscription)
+
+ canceller.run()
+ verify(subscription).cancel()
+ }
+
+ @Test
+ fun testBindAndLoad_noCancelAfterOnComplete() {
+ val callback = object : ControlsBindingController.LoadCallback {
+ override fun error(message: String) {}
+
+ override fun accept(t: List<Control>) {}
+ }
+ val subscription = mock(IControlsSubscription::class.java)
+
+ val canceller = controller.bindAndLoad(TEST_COMPONENT_NAME_1, callback)
+
+ verify(providers[0]).maybeBindAndLoad(capture(loadSubscriberCaptor))
+ val b = Binder()
+ loadSubscriberCaptor.value.onSubscribe(b, subscription)
+
+ loadSubscriberCaptor.value.onComplete(b)
+ canceller.run()
+ verify(subscription, never()).cancel()
+ }
+
+ @Test
+ fun testLoad_onCompleteRemovesTimeout() {
+ val callback = object : ControlsBindingController.LoadCallback {
+ override fun error(message: String) {}
+
+ override fun accept(t: List<Control>) {}
+ }
+ val subscription = mock(IControlsSubscription::class.java)
+
+ val canceller = controller.bindAndLoad(TEST_COMPONENT_NAME_1, callback)
+
+ verify(providers[0]).maybeBindAndLoad(capture(subscriberCaptor))
+ val b = Binder()
+ subscriberCaptor.value.onSubscribe(b, subscription)
+
+ subscriberCaptor.value.onComplete(b)
+ verify(providers[0]).cancelLoadTimeout()
+ }
+
+ @Test
+ fun testLoad_onErrorRemovesTimeout() {
+ val callback = object : ControlsBindingController.LoadCallback {
+ override fun error(message: String) {}
+
+ override fun accept(t: List<Control>) {}
+ }
+ val subscription = mock(IControlsSubscription::class.java)
+
+ val canceller = controller.bindAndLoad(TEST_COMPONENT_NAME_1, callback)
+
+ verify(providers[0]).maybeBindAndLoad(capture(subscriberCaptor))
+ val b = Binder()
+ subscriberCaptor.value.onSubscribe(b, subscription)
+
+ subscriberCaptor.value.onError(b, "")
+ verify(providers[0]).cancelLoadTimeout()
+ }
+
+ @Test
+ fun testBindAndLoad_noCancelAfterOnError() {
+ val callback = object : ControlsBindingController.LoadCallback {
+ override fun error(message: String) {}
+
+ override fun accept(t: List<Control>) {}
+ }
+ val subscription = mock(IControlsSubscription::class.java)
+
+ val canceller = controller.bindAndLoad(TEST_COMPONENT_NAME_1, callback)
+
+ verify(providers[0]).maybeBindAndLoad(capture(loadSubscriberCaptor))
+ val b = Binder()
+ loadSubscriberCaptor.value.onSubscribe(b, subscription)
+
+ loadSubscriberCaptor.value.onError(b, "")
+ canceller.run()
+ verify(subscription, never()).cancel()
+ }
+
+ @Test
fun testBindService() {
controller.bindService(TEST_COMPONENT_NAME_1)
executor.runAllReady()
@@ -115,8 +225,13 @@
executor.runAllReady()
+ val subs = mock(IControlsSubscription::class.java)
verify(providers[0]).maybeBindAndSubscribe(
+ capture(listStringCaptor), capture(subscriberCaptor))
+ assertEquals(listStringCaptor.value,
listOf(controlInfo1.controlId, controlInfo2.controlId))
+
+ subscriberCaptor.value.onSubscribe(providers[0].token, subs)
}
@Test
@@ -126,7 +241,7 @@
executor.runAllReady()
- verify(providers[0], never()).unsubscribe()
+ verify(providers[0], never()).cancelSubscription(any())
}
@Test
@@ -137,12 +252,21 @@
StructureInfo(TEST_COMPONENT_NAME_1, "Home", listOf(controlInfo1, controlInfo2))
controller.subscribe(structure)
-
- controller.unsubscribe()
-
executor.runAllReady()
- verify(providers[0]).unsubscribe()
+ val subs = mock(IControlsSubscription::class.java)
+ verify(providers[0]).maybeBindAndSubscribe(
+ capture(listStringCaptor), capture(subscriberCaptor))
+ assertEquals(listStringCaptor.value,
+ listOf(controlInfo1.controlId, controlInfo2.controlId))
+
+ subscriberCaptor.value.onSubscribe(providers[0].token, subs)
+ executor.runAllReady()
+
+ controller.unsubscribe()
+ executor.runAllReady()
+
+ verify(providers[0]).cancelSubscription(subs)
}
@Test
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 c70c56a..f9c9815 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
@@ -346,6 +346,88 @@
}
@Test
+ fun testCancelLoad() {
+ val canceller = object : Runnable {
+ var ran = false
+ override fun run() {
+ ran = true
+ }
+ }
+ `when`(bindingController.bindAndLoad(any(), any())).thenReturn(canceller)
+
+ var loaded = false
+ controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
+ delayableExecutor.runAllReady()
+ controller.loadForComponent(TEST_COMPONENT, Consumer {
+ loaded = true
+ })
+
+ controller.cancelLoad()
+ delayableExecutor.runAllReady()
+
+ assertFalse(loaded)
+ assertTrue(canceller.ran)
+ }
+
+ @Test
+ fun testCancelLoad_noCancelAfterSuccessfulLoad() {
+ val canceller = object : Runnable {
+ var ran = false
+ override fun run() {
+ ran = true
+ }
+ }
+ `when`(bindingController.bindAndLoad(any(), any())).thenReturn(canceller)
+
+ var loaded = false
+ controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
+ delayableExecutor.runAllReady()
+ controller.loadForComponent(TEST_COMPONENT, Consumer {
+ loaded = true
+ })
+
+ verify(bindingController).bindAndLoad(eq(TEST_COMPONENT),
+ capture(controlLoadCallbackCaptor))
+
+ controlLoadCallbackCaptor.value.accept(emptyList())
+
+ controller.cancelLoad()
+ delayableExecutor.runAllReady()
+
+ assertTrue(loaded)
+ assertFalse(canceller.ran)
+ }
+
+ @Test
+ fun testCancelLoad_noCancelAfterErrorLoad() {
+ val canceller = object : Runnable {
+ var ran = false
+ override fun run() {
+ ran = true
+ }
+ }
+ `when`(bindingController.bindAndLoad(any(), any())).thenReturn(canceller)
+
+ var loaded = false
+ controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
+ delayableExecutor.runAllReady()
+ controller.loadForComponent(TEST_COMPONENT, Consumer {
+ loaded = true
+ })
+
+ verify(bindingController).bindAndLoad(eq(TEST_COMPONENT),
+ capture(controlLoadCallbackCaptor))
+
+ controlLoadCallbackCaptor.value.error("")
+
+ controller.cancelLoad()
+ delayableExecutor.runAllReady()
+
+ assertTrue(loaded)
+ assertFalse(canceller.ran)
+ }
+
+ @Test
fun testFavoriteInformationModifiedOnLoad() {
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
delayableExecutor.runAllReady()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
index fd92ad0..2d3757c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License");
+ * Licensed under the Apache License, Version 2.0 (149the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
@@ -43,6 +43,7 @@
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -83,7 +84,6 @@
context,
executor,
actionCallbackService,
- subscriberService,
UserHandle.of(0),
componentName
)
@@ -144,9 +144,22 @@
}
@Test
+ fun testMaybeBindAndLoad_timeoutCancelled() {
+ manager.maybeBindAndLoad(subscriberService)
+ executor.runAllReady()
+
+ manager.cancelLoadTimeout()
+
+ executor.advanceClockToLast()
+ executor.runAllReady()
+
+ verify(subscriberService, never()).onError(any(), anyString())
+ }
+
+ @Test
fun testMaybeBindAndSubscribe() {
val list = listOf("TEST_ID")
- manager.maybeBindAndSubscribe(list)
+ manager.maybeBindAndSubscribe(list, subscriberService)
executor.runAllReady()
assertTrue(mContext.isBound(componentName))
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
new file mode 100644
index 0000000..ff5c8d4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt
@@ -0,0 +1,146 @@
+/*
+ * 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.controls.controller
+
+import android.content.ComponentName
+import android.os.Binder
+import android.service.controls.Control
+import android.service.controls.IControlsSubscription
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.time.FakeSystemClock
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class StatefulControlSubscriberTest : SysuiTestCase() {
+
+ @Mock
+ private lateinit var controller: ControlsController
+
+ @Mock
+ private lateinit var subscription: IControlsSubscription
+
+ @Mock
+ private lateinit var provider: ControlsProviderLifecycleManager
+
+ @Mock
+ private lateinit var control: Control
+
+ private val executor = FakeExecutor(FakeSystemClock())
+ private val token = Binder()
+ private val badToken = Binder()
+
+ private val TEST_COMPONENT = ComponentName("TEST_PKG", "TEST_CLS_1")
+
+ private lateinit var scs: StatefulControlSubscriber
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ `when`(provider.componentName).thenReturn(TEST_COMPONENT)
+ `when`(provider.token).thenReturn(token)
+ scs = StatefulControlSubscriber(controller, provider, executor)
+ }
+
+ @Test
+ fun testOnSubscribe() {
+ scs.onSubscribe(token, subscription)
+
+ executor.runAllReady()
+ verify(provider).startSubscription(subscription)
+ }
+
+ @Test
+ fun testOnSubscribe_badToken() {
+ scs.onSubscribe(badToken, subscription)
+
+ executor.runAllReady()
+ verify(provider, never()).startSubscription(subscription)
+ }
+
+ @Test
+ fun testOnNext() {
+ scs.onSubscribe(token, subscription)
+ scs.onNext(token, control)
+
+ executor.runAllReady()
+ verify(controller).refreshStatus(TEST_COMPONENT, control)
+ }
+
+ @Test
+ fun testOnNext_multiple() {
+ scs.onSubscribe(token, subscription)
+ scs.onNext(token, control)
+ scs.onNext(token, control)
+ scs.onNext(token, control)
+
+ executor.runAllReady()
+ verify(controller, times(3)).refreshStatus(TEST_COMPONENT, control)
+ }
+
+ @Test
+ fun testOnNext_noRefreshBeforeSubscribe() {
+ scs.onNext(token, control)
+
+ executor.runAllReady()
+ verify(controller, never()).refreshStatus(TEST_COMPONENT, control)
+ }
+
+ @Test
+ fun testOnNext_noRefreshAfterCancel() {
+ scs.onSubscribe(token, subscription)
+ executor.runAllReady()
+
+ scs.cancel()
+ scs.onNext(token, control)
+
+ executor.runAllReady()
+ verify(controller, never()).refreshStatus(TEST_COMPONENT, control)
+ }
+
+ @Test
+ fun testOnNext_noRefreshAfterError() {
+ scs.onSubscribe(token, subscription)
+ scs.onError(token, "Error")
+ scs.onNext(token, control)
+
+ executor.runAllReady()
+ verify(controller, never()).refreshStatus(TEST_COMPONENT, control)
+ }
+
+ @Test
+ fun testOnNext_noRefreshAfterComplete() {
+ scs.onSubscribe(token, subscription)
+ scs.onComplete(token)
+ scs.onNext(token, control)
+
+ executor.runAllReady()
+ verify(controller, never()).refreshStatus(TEST_COMPONENT, control)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
index 9117ea8..f535351 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -248,31 +248,6 @@
}
@Test
- public void pausingAod_softBlanks_withSpuriousSensorDuringPause() throws Exception {
- mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
- mScreen.transitionTo(INITIALIZED, DOZE_AOD);
- mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
- mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
-
- reset(mDozeHost);
- mSensor.sendSensorEvent(1);
- verify(mDozeHost).setAodDimmingScrim(eq(1f));
- }
-
- @Test
- public void screenOff_softBlanks() throws Exception {
- mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
- mScreen.transitionTo(INITIALIZED, DOZE_AOD);
- mScreen.transitionTo(DOZE_AOD, DOZE);
- verify(mDozeHost).setAodDimmingScrim(eq(1f));
-
- reset(mDozeHost);
- mScreen.transitionTo(DOZE, DOZE_AOD);
- mSensor.sendSensorEvent(2);
- verify(mDozeHost).setAodDimmingScrim(eq(0f));
- }
-
- @Test
public void pausingAod_unblanksAfterSensor() throws Exception {
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
similarity index 63%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
index 1693e7f..f9c62e1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInterruptionStateProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.systemui.statusbar;
+package com.android.systemui.statusbar.notification.interruption;
import static android.app.Notification.FLAG_BUBBLE;
@@ -30,15 +30,14 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Notification;
import android.app.PendingIntent;
-import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.hardware.display.AmbientDisplayConfiguration;
+import android.os.Handler;
import android.os.PowerManager;
import android.os.RemoteException;
import android.service.dreams.IDreamManager;
@@ -50,7 +49,6 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationFilter;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -68,7 +66,7 @@
*/
@RunWith(AndroidTestingRunner.class)
@SmallTest
-public class NotificationInterruptionStateProviderTest extends SysuiTestCase {
+public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
@Mock
PowerManager mPowerManager;
@@ -81,38 +79,36 @@
@Mock
StatusBarStateController mStatusBarStateController;
@Mock
- NotificationPresenter mPresenter;
- @Mock
HeadsUpManager mHeadsUpManager;
@Mock
- NotificationInterruptionStateProvider.HeadsUpSuppressor mHeadsUpSuppressor;
- @Mock
BatteryController mBatteryController;
+ @Mock
+ Handler mMockHandler;
- private NotificationInterruptionStateProvider mNotifInterruptionStateProvider;
+ private NotificationInterruptStateProviderImpl mNotifInterruptionStateProvider;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mNotifInterruptionStateProvider =
- new TestableNotificationInterruptionStateProvider(mContext,
+ new NotificationInterruptStateProviderImpl(
+ mContext.getContentResolver(),
mPowerManager,
mDreamManager,
mAmbientDisplayConfiguration,
mNotificationFilter,
+ mBatteryController,
mStatusBarStateController,
- mBatteryController);
+ mHeadsUpManager,
+ mMockHandler);
- mNotifInterruptionStateProvider.setUpWithPresenter(
- mPresenter,
- mHeadsUpManager,
- mHeadsUpSuppressor);
+ mNotifInterruptionStateProvider.mUseHeadsUp = true;
}
/**
* Sets up the state such that any requests to
- * {@link NotificationInterruptionStateProvider#canAlertCommon(NotificationEntry)} will
+ * {@link NotificationInterruptStateProviderImpl#canAlertCommon(NotificationEntry)} will
* pass as long its provided NotificationEntry fulfills group suppression check.
*/
private void ensureStateForAlertCommon() {
@@ -121,17 +117,16 @@
/**
* Sets up the state such that any requests to
- * {@link NotificationInterruptionStateProvider#canAlertAwakeCommon(NotificationEntry)} will
+ * {@link NotificationInterruptStateProviderImpl#canAlertAwakeCommon(NotificationEntry)} will
* pass as long its provided NotificationEntry fulfills launch fullscreen check.
*/
private void ensureStateForAlertAwakeCommon() {
- when(mPresenter.isDeviceInVrMode()).thenReturn(false);
when(mHeadsUpManager.isSnoozed(any())).thenReturn(false);
}
/**
* Sets up the state such that any requests to
- * {@link NotificationInterruptionStateProvider#shouldHeadsUp(NotificationEntry)} will
+ * {@link NotificationInterruptStateProviderImpl#shouldHeadsUp(NotificationEntry)} will
* pass as long its provided NotificationEntry fulfills importance & DND checks.
*/
private void ensureStateForHeadsUpWhenAwake() throws RemoteException {
@@ -141,12 +136,11 @@
when(mStatusBarStateController.isDozing()).thenReturn(false);
when(mDreamManager.isDreaming()).thenReturn(false);
when(mPowerManager.isScreenOn()).thenReturn(true);
- when(mHeadsUpSuppressor.canHeadsUp(any(), any())).thenReturn(true);
}
/**
* Sets up the state such that any requests to
- * {@link NotificationInterruptionStateProvider#shouldHeadsUp(NotificationEntry)} will
+ * {@link NotificationInterruptStateProviderImpl#shouldHeadsUp(NotificationEntry)} will
* pass as long its provided NotificationEntry fulfills importance & DND checks.
*/
private void ensureStateForHeadsUpWhenDozing() {
@@ -158,7 +152,7 @@
/**
* Sets up the state such that any requests to
- * {@link NotificationInterruptionStateProvider#shouldBubbleUp(NotificationEntry)} will
+ * {@link NotificationInterruptStateProviderImpl#shouldBubbleUp(NotificationEntry)} will
* pass as long its provided NotificationEntry fulfills importance & bubble checks.
*/
private void ensureStateForBubbleUp() {
@@ -166,75 +160,53 @@
ensureStateForAlertAwakeCommon();
}
- /**
- * Ensure that the disabled state is set correctly.
- */
@Test
- public void testDisableNotificationAlerts() {
- // Enabled by default
- assertThat(mNotifInterruptionStateProvider.areNotificationAlertsDisabled()).isFalse();
-
- // Disable alerts
- mNotifInterruptionStateProvider.setDisableNotificationAlerts(true);
- assertThat(mNotifInterruptionStateProvider.areNotificationAlertsDisabled()).isTrue();
-
- // Enable alerts
- mNotifInterruptionStateProvider.setDisableNotificationAlerts(false);
- assertThat(mNotifInterruptionStateProvider.areNotificationAlertsDisabled()).isFalse();
- }
-
- /**
- * Ensure that the disabled alert state effects whether HUNs are enabled.
- */
- @Test
- public void testHunSettingsChange_enabled_butAlertsDisabled() {
- // Set up but without a mock change observer
- mNotifInterruptionStateProvider.setUpWithPresenter(
- mPresenter,
- mHeadsUpManager,
- mHeadsUpSuppressor);
-
- // HUNs enabled by default
- assertThat(mNotifInterruptionStateProvider.getUseHeadsUp()).isTrue();
-
- // Set alerts disabled
- mNotifInterruptionStateProvider.setDisableNotificationAlerts(true);
-
- // No more HUNs
- assertThat(mNotifInterruptionStateProvider.getUseHeadsUp()).isFalse();
- }
-
- /**
- * Alerts can happen.
- */
- @Test
- public void testCanAlertCommon_true() {
- ensureStateForAlertCommon();
+ public void testDefaultSuppressorDoesNotSuppress() {
+ // GIVEN a suppressor without any overrides
+ final NotificationInterruptSuppressor defaultSuppressor =
+ new NotificationInterruptSuppressor() {
+ @Override
+ public String getName() {
+ return "defaultSuppressor";
+ }
+ };
NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
- assertThat(mNotifInterruptionStateProvider.canAlertCommon(entry)).isTrue();
+
+ // THEN this suppressor doesn't suppress anything by default
+ assertThat(defaultSuppressor.suppressAwakeHeadsUp(entry)).isFalse();
+ assertThat(defaultSuppressor.suppressAwakeInterruptions(entry)).isFalse();
+ assertThat(defaultSuppressor.suppressInterruptions(entry)).isFalse();
}
- /**
- * Filtered out notifications don't alert.
- */
@Test
- public void testCanAlertCommon_false_filteredOut() {
- ensureStateForAlertCommon();
- when(mNotificationFilter.shouldFilterOut(any())).thenReturn(true);
+ public void testShouldHeadsUpAwake() throws RemoteException {
+ ensureStateForHeadsUpWhenAwake();
- NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
- assertThat(mNotifInterruptionStateProvider.canAlertCommon(entry)).isFalse();
+ NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
+ assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isTrue();
}
- /**
- * Grouped notifications have different alerting behaviours, sometimes the alert for a
- * grouped notification may be suppressed {@link android.app.Notification#GROUP_ALERT_CHILDREN}.
- */
@Test
- public void testCanAlertCommon_false_suppressedForGroups() {
- ensureStateForAlertCommon();
+ public void testShouldNotHeadsUpAwake_flteredOut() throws RemoteException {
+ // GIVEN state for "heads up when awake" is true
+ ensureStateForHeadsUpWhenAwake();
+ // WHEN this entry should be filtered out
+ NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
+ when(mNotificationFilter.shouldFilterOut(entry)).thenReturn(true);
+
+ // THEN we shouldn't heads up this entry
+ assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
+ }
+
+ @Test
+ public void testShouldNotHeadsUp_suppressedForGroups() throws RemoteException {
+ // GIVEN state for "heads up when awake" is true
+ ensureStateForHeadsUpWhenAwake();
+
+ // WHEN the alert for a grouped notification is suppressed
+ // see {@link android.app.Notification#GROUP_ALERT_CHILDREN}
NotificationEntry entry = new NotificationEntryBuilder()
.setPkg("a")
.setOpPkg("a")
@@ -247,40 +219,40 @@
.setImportance(IMPORTANCE_DEFAULT)
.build();
- assertThat(mNotifInterruptionStateProvider.canAlertCommon(entry)).isFalse();
+ // THEN this entry shouldn't HUN
+ assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
}
- /**
- * HUNs while dozing can happen.
- */
@Test
- public void testShouldHeadsUpWhenDozing_true() {
+ public void testShouldHeadsUpWhenDozing() {
ensureStateForHeadsUpWhenDozing();
NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isTrue();
}
- /**
- * Ambient display can show HUNs for new notifications, this may be disabled.
- */
@Test
- public void testShouldHeadsUpWhenDozing_false_pulseDisabled() {
+ public void testShouldNotHeadsUpWhenDozing_pulseDisabled() {
+ // GIVEN state for "heads up when dozing" is true
ensureStateForHeadsUpWhenDozing();
+
+ // WHEN pulsing (HUNs when dozing) is disabled
when(mAmbientDisplayConfiguration.pulseOnNotificationEnabled(anyInt())).thenReturn(false);
+ // THEN this entry shouldn't HUN
NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
}
- /**
- * If the device is not in ambient display or sleeping then we don't HUN.
- */
@Test
- public void testShouldHeadsUpWhenDozing_false_notDozing() {
+ public void testShouldNotHeadsUpWhenDozing_notDozing() {
+ // GIVEN state for "heads up when dozing" is true
ensureStateForHeadsUpWhenDozing();
+
+ // WHEN we're not dozing (in ambient display or sleeping)
when(mStatusBarStateController.isDozing()).thenReturn(false);
+ // THEN this entry shouldn't HUN
NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
}
@@ -290,7 +262,7 @@
* {@link android.app.NotificationManager.Policy#SUPPRESSED_EFFECT_AMBIENT}.
*/
@Test
- public void testShouldHeadsUpWhenDozing_false_suppressingAmbient() {
+ public void testShouldNotHeadsUpWhenDozing_suppressingAmbient() {
ensureStateForHeadsUpWhenDozing();
NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
@@ -301,23 +273,18 @@
assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
}
- /**
- * Notifications that are < {@link android.app.NotificationManager#IMPORTANCE_DEFAULT} don't
- * get to pulse.
- */
@Test
- public void testShouldHeadsUpWhenDozing_false_lessImportant() {
+ public void testShouldNotHeadsUpWhenDozing_lessImportant() {
ensureStateForHeadsUpWhenDozing();
+ // Notifications that are < {@link android.app.NotificationManager#IMPORTANCE_DEFAULT} don't
+ // get to pulse
NotificationEntry entry = createNotification(IMPORTANCE_LOW);
assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
}
- /**
- * Heads up can happen.
- */
@Test
- public void testShouldHeadsUp_true() throws RemoteException {
+ public void testShouldHeadsUp() throws RemoteException {
ensureStateForHeadsUpWhenAwake();
NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
@@ -325,38 +292,11 @@
}
/**
- * Heads up notifications can be disabled in general.
- */
- @Test
- public void testShouldHeadsUp_false_noHunsAllowed() throws RemoteException {
- ensureStateForHeadsUpWhenAwake();
-
- // Set alerts disabled, this should cause heads up to be false
- mNotifInterruptionStateProvider.setDisableNotificationAlerts(true);
- assertThat(mNotifInterruptionStateProvider.getUseHeadsUp()).isFalse();
-
- NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
- assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
- }
-
- /**
- * If the device is dozing, we don't show as heads up.
- */
- @Test
- public void testShouldHeadsUp_false_dozing() throws RemoteException {
- ensureStateForHeadsUpWhenAwake();
- when(mStatusBarStateController.isDozing()).thenReturn(true);
-
- NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
- assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
- }
-
- /**
* If the notification is a bubble, and the user is not on AOD / lockscreen, then
* the bubble is shown rather than the heads up.
*/
@Test
- public void testShouldHeadsUp_false_bubble() throws RemoteException {
+ public void testShouldNotHeadsUp_bubble() throws RemoteException {
ensureStateForHeadsUpWhenAwake();
// Bubble bit only applies to interruption when we're in the shade
@@ -369,7 +309,7 @@
* If we're not allowed to alert in general, we shouldn't be shown as heads up.
*/
@Test
- public void testShouldHeadsUp_false_alertCommonFalse() throws RemoteException {
+ public void testShouldNotHeadsUp_filtered() throws RemoteException {
ensureStateForHeadsUpWhenAwake();
// Make canAlertCommon false by saying it's filtered out
when(mNotificationFilter.shouldFilterOut(any())).thenReturn(true);
@@ -383,7 +323,7 @@
* {@link android.app.NotificationManager.Policy#SUPPRESSED_EFFECT_PEEK}.
*/
@Test
- public void testShouldHeadsUp_false_suppressPeek() throws RemoteException {
+ public void testShouldNotHeadsUp_suppressPeek() throws RemoteException {
ensureStateForHeadsUpWhenAwake();
NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
@@ -399,7 +339,7 @@
* to show as a heads up.
*/
@Test
- public void testShouldHeadsUp_false_lessImportant() throws RemoteException {
+ public void testShouldNotHeadsUp_lessImportant() throws RemoteException {
ensureStateForHeadsUpWhenAwake();
NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
@@ -410,7 +350,7 @@
* If the device is not in use then we shouldn't be shown as heads up.
*/
@Test
- public void testShouldHeadsUp_false_deviceNotInUse() throws RemoteException {
+ public void testShouldNotHeadsUp_deviceNotInUse() throws RemoteException {
ensureStateForHeadsUpWhenAwake();
NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
@@ -424,61 +364,58 @@
assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
}
- /**
- * If something wants to suppress this heads up, then it shouldn't be shown as a heads up.
- */
@Test
- public void testShouldHeadsUp_false_suppressed() throws RemoteException {
+ public void testShouldNotHeadsUp_headsUpSuppressed() throws RemoteException {
ensureStateForHeadsUpWhenAwake();
- when(mHeadsUpSuppressor.canHeadsUp(any(), any())).thenReturn(false);
+
+ // If a suppressor is suppressing heads up, then it shouldn't be shown as a heads up.
+ mNotifInterruptionStateProvider.addSuppressor(mSuppressAwakeHeadsUp);
NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
- verify(mHeadsUpSuppressor).canHeadsUp(any(), any());
}
- /**
- * On screen alerts don't happen when the device is in VR Mode.
- */
@Test
- public void testCanAlertAwakeCommon__false_vrMode() {
- ensureStateForAlertAwakeCommon();
- when(mPresenter.isDeviceInVrMode()).thenReturn(true);
+ public void testShouldNotHeadsUpAwake_awakeInterruptsSuppressed() throws RemoteException {
+ ensureStateForHeadsUpWhenAwake();
- NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
- assertThat(mNotifInterruptionStateProvider.canAlertAwakeCommon(entry)).isFalse();
+ // If a suppressor is suppressing heads up, then it shouldn't be shown as a heads up.
+ mNotifInterruptionStateProvider.addSuppressor(mSuppressAwakeInterruptions);
+
+ NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
+ assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
}
/**
* On screen alerts don't happen when the notification is snoozed.
*/
@Test
- public void testCanAlertAwakeCommon_false_snoozedPackage() {
- ensureStateForAlertAwakeCommon();
- when(mHeadsUpManager.isSnoozed(any())).thenReturn(true);
-
+ public void testShouldNotHeadsUp_snoozedPackage() {
NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
- assertThat(mNotifInterruptionStateProvider.canAlertAwakeCommon(entry)).isFalse();
+ ensureStateForAlertAwakeCommon();
+
+ when(mHeadsUpManager.isSnoozed(entry.getSbn().getPackageName())).thenReturn(true);
+
+ assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
}
- /**
- * On screen alerts don't happen when that package has just launched fullscreen.
- */
+
@Test
- public void testCanAlertAwakeCommon_false_justLaunchedFullscreen() {
+ public void testShouldNotHeadsUp_justLaunchedFullscreen() {
ensureStateForAlertAwakeCommon();
+ // On screen alerts don't happen when that package has just launched fullscreen.
NotificationEntry entry = createNotification(IMPORTANCE_DEFAULT);
entry.notifyFullScreenIntentLaunched();
- assertThat(mNotifInterruptionStateProvider.canAlertAwakeCommon(entry)).isFalse();
+ assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
}
/**
* Bubbles can happen.
*/
@Test
- public void testShouldBubbleUp_true() {
+ public void testShouldBubbleUp() {
ensureStateForBubbleUp();
assertThat(mNotifInterruptionStateProvider.shouldBubbleUp(createBubble())).isTrue();
}
@@ -487,7 +424,7 @@
* If the notification doesn't have permission to bubble, it shouldn't bubble.
*/
@Test
- public void shouldBubbleUp_false_notAllowedToBubble() {
+ public void shouldNotBubbleUp_notAllowedToBubble() {
ensureStateForBubbleUp();
NotificationEntry entry = createBubble();
@@ -502,7 +439,7 @@
* If the notification isn't a bubble, it should definitely not show as a bubble.
*/
@Test
- public void shouldBubbleUp_false_notABubble() {
+ public void shouldNotBubbleUp_notABubble() {
ensureStateForBubbleUp();
NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
@@ -517,7 +454,7 @@
* If the notification doesn't have bubble metadata, it shouldn't bubble.
*/
@Test
- public void shouldBubbleUp_false_invalidMetadata() {
+ public void shouldNotBubbleUp_invalidMetadata() {
ensureStateForBubbleUp();
NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
@@ -529,24 +466,18 @@
assertThat(mNotifInterruptionStateProvider.shouldBubbleUp(entry)).isFalse();
}
- /**
- * If the notification can't heads up in general, it shouldn't bubble.
- */
@Test
- public void shouldBubbleUp_false_alertAwakeCommonFalse() {
+ public void shouldNotBubbleUp_suppressedInterruptions() {
ensureStateForBubbleUp();
- // Make alert common return false by pretending we're in VR mode
- when(mPresenter.isDeviceInVrMode()).thenReturn(true);
+ // If the notification can't heads up in general, it shouldn't bubble.
+ mNotifInterruptionStateProvider.addSuppressor(mSuppressInterruptions);
assertThat(mNotifInterruptionStateProvider.shouldBubbleUp(createBubble())).isFalse();
}
- /**
- * If the notification can't heads up in general, it shouldn't bubble.
- */
@Test
- public void shouldBubbleUp_false_alertCommonFalse() {
+ public void shouldNotBubbleUp_filteredOut() {
ensureStateForBubbleUp();
// Make canAlertCommon false by saying it's filtered out
@@ -592,20 +523,45 @@
.build();
}
- /**
- * Testable class overriding constructor.
- */
- public static class TestableNotificationInterruptionStateProvider extends
- NotificationInterruptionStateProvider {
-
- TestableNotificationInterruptionStateProvider(Context context,
- PowerManager powerManager, IDreamManager dreamManager,
- AmbientDisplayConfiguration ambientDisplayConfiguration,
- NotificationFilter notificationFilter,
- StatusBarStateController statusBarStateController,
- BatteryController batteryController) {
- super(context, powerManager, dreamManager, ambientDisplayConfiguration,
- notificationFilter, batteryController, statusBarStateController);
+ private final NotificationInterruptSuppressor
+ mSuppressAwakeHeadsUp =
+ new NotificationInterruptSuppressor() {
+ @Override
+ public String getName() {
+ return "suppressAwakeHeadsUp";
}
- }
+
+ @Override
+ public boolean suppressAwakeHeadsUp(NotificationEntry entry) {
+ return true;
+ }
+ };
+
+ private final NotificationInterruptSuppressor
+ mSuppressAwakeInterruptions =
+ new NotificationInterruptSuppressor() {
+ @Override
+ public String getName() {
+ return "suppressAwakeInterruptions";
+ }
+
+ @Override
+ public boolean suppressAwakeInterruptions(NotificationEntry entry) {
+ return true;
+ }
+ };
+
+ private final NotificationInterruptSuppressor
+ mSuppressInterruptions =
+ new NotificationInterruptSuppressor() {
+ @Override
+ public String getName() {
+ return "suppressInterruptions";
+ }
+
+ @Override
+ public boolean suppressInterruptions(NotificationEntry entry) {
+ return true;
+ }
+ };
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index 5d0349d..a21a047 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -56,12 +56,12 @@
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger;
import com.android.systemui.statusbar.notification.NotificationFilter;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
@@ -108,7 +108,7 @@
@Mock private NotificationEntryListener mEntryListener;
@Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback;
@Mock private HeadsUpManager mHeadsUpManager;
- @Mock private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+ @Mock private NotificationInterruptStateProvider mNotificationInterruptionStateProvider;
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private NotificationGutsManager mGutsManager;
@Mock private NotificationRemoteInputManager mRemoteInputManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java
new file mode 100644
index 0000000..291c039
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.phone;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.View;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class KeyguardIndicationTextViewTest extends SysuiTestCase {
+
+ private KeyguardIndicationTextView mKeyguardIndicationTextView;
+
+ @Before
+ public void setup() {
+ mKeyguardIndicationTextView = new KeyguardIndicationTextView(mContext);
+ }
+
+ @Test
+ public void switchIndication_null_hideIndication() {
+ mKeyguardIndicationTextView.switchIndication(null /* text */);
+
+ assertThat(mKeyguardIndicationTextView.getVisibility()).isEqualTo(View.INVISIBLE);
+ assertThat(mKeyguardIndicationTextView.getText()).isEqualTo("");
+ }
+
+ @Test
+ public void switchIndication_emptyText_hideIndication() {
+ mKeyguardIndicationTextView.switchIndication("" /* text */);
+
+ assertThat(mKeyguardIndicationTextView.getVisibility()).isEqualTo(View.INVISIBLE);
+ assertThat(mKeyguardIndicationTextView.getText()).isEqualTo("");
+ }
+
+ @Test
+ public void switchIndication_newText_updateProperly() {
+ mKeyguardIndicationTextView.switchIndication("test_indication" /* text */);
+
+ assertThat(mKeyguardIndicationTextView.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mKeyguardIndicationTextView.getText()).isEqualTo("test_indication");
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
index c5b6969..cc2d1c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
@@ -37,7 +37,7 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationShadeWindowBlurController;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -81,7 +81,7 @@
@Mock private DockManager mDockManager;
@Mock private NotificationPanelViewController mNotificationPanelViewController;
@Mock private NotificationStackScrollLayout mNotificationStackScrollLayout;
- @Mock private NotificationShadeWindowBlurController mNotificationShadeWindowBlurController;
+ @Mock private NotificationShadeDepthController mNotificationShadeDepthController;
@Mock private SuperStatusBarViewFactory mStatusBarViewFactory;
@Before
@@ -116,7 +116,7 @@
new CommandQueue(mContext),
mShadeController,
mDockManager,
- mNotificationShadeWindowBlurController,
+ mNotificationShadeDepthController,
mView,
mNotificationPanelViewController,
mStatusBarViewFactory);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 1e4df27..b9c5b7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -67,10 +67,10 @@
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -183,7 +183,7 @@
mock(StatusBarRemoteInputCallback.class), mock(NotificationGroupManager.class),
mock(NotificationLockscreenUserManager.class),
mKeyguardStateController,
- mock(NotificationInterruptionStateProvider.class), mock(MetricsLogger.class),
+ mock(NotificationInterruptStateProvider.class), mock(MetricsLogger.class),
mock(LockPatternUtils.class), mHandler, mHandler, mUiBgExecutor,
mActivityIntentHelper, mBubbleController, mShadeController, mFeatureFlags,
mNotifPipeline, mNotifCollection)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index b9d2d22..318e9b8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -16,8 +16,9 @@
import static android.view.Display.DEFAULT_DISPLAY;
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Notification;
@@ -35,6 +36,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.logging.testing.FakeMetricsLogger;
+import com.android.systemui.ForegroundServiceNotificationListener;
import com.android.systemui.InitController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -48,12 +50,12 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -62,6 +64,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import java.util.ArrayList;
@@ -72,6 +75,9 @@
private StatusBarNotificationPresenter mStatusBarNotificationPresenter;
+ private NotificationInterruptStateProvider mNotificationInterruptStateProvider =
+ mock(NotificationInterruptStateProvider.class);
+ private NotificationInterruptSuppressor mInterruptSuppressor;
private CommandQueue mCommandQueue;
private FakeMetricsLogger mMetricsLogger;
private ShadeController mShadeController = mock(ShadeController.class);
@@ -95,11 +101,11 @@
mDependency.injectMockDependency(NotificationViewHierarchyManager.class);
mDependency.injectMockDependency(NotificationRemoteInputManager.Callback.class);
mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
- mDependency.injectMockDependency(NotificationInterruptionStateProvider.class);
mDependency.injectMockDependency(NotificationMediaManager.class);
mDependency.injectMockDependency(VisualStabilityManager.class);
mDependency.injectMockDependency(NotificationGutsManager.class);
mDependency.injectMockDependency(NotificationShadeWindowController.class);
+ mDependency.injectMockDependency(ForegroundServiceNotificationListener.class);
NotificationEntryManager entryManager =
mDependency.injectMockDependency(NotificationEntryManager.class);
when(entryManager.getActiveNotificationsForCurrentUser()).thenReturn(new ArrayList<>());
@@ -107,18 +113,25 @@
NotificationShadeWindowView notificationShadeWindowView =
mock(NotificationShadeWindowView.class);
when(notificationShadeWindowView.getResources()).thenReturn(mContext.getResources());
+
mStatusBarNotificationPresenter = new StatusBarNotificationPresenter(mContext,
mock(NotificationPanelViewController.class), mock(HeadsUpManagerPhone.class),
notificationShadeWindowView, mock(NotificationListContainerViewGroup.class),
mock(DozeScrimController.class), mock(ScrimController.class),
mock(ActivityLaunchAnimator.class), mock(DynamicPrivacyController.class),
- mock(NotificationAlertingManager.class), mock(KeyguardStateController.class),
+ mock(KeyguardStateController.class),
mock(KeyguardIndicationController.class), mStatusBar,
- mock(ShadeControllerImpl.class), mCommandQueue, mInitController);
+ mock(ShadeControllerImpl.class), mCommandQueue, mInitController,
+ mNotificationInterruptStateProvider);
+ mInitController.executePostInitTasks();
+ ArgumentCaptor<NotificationInterruptSuppressor> suppressorCaptor =
+ ArgumentCaptor.forClass(NotificationInterruptSuppressor.class);
+ verify(mNotificationInterruptStateProvider).addSuppressor(suppressorCaptor.capture());
+ mInterruptSuppressor = suppressorCaptor.getValue();
}
@Test
- public void testHeadsUp_disabledStatusBar() {
+ public void testSuppressHeadsUp_disabledStatusBar() {
Notification n = new Notification.Builder(getContext(), "a").build();
NotificationEntry entry = new NotificationEntryBuilder()
.setPkg("a")
@@ -130,12 +143,12 @@
false /* animate */);
TestableLooper.get(this).processAllMessages();
- assertFalse("The panel shouldn't allow heads up while disabled",
- mStatusBarNotificationPresenter.canHeadsUp(entry, entry.getSbn()));
+ assertTrue("The panel should suppress heads up while disabled",
+ mInterruptSuppressor.suppressAwakeHeadsUp(entry));
}
@Test
- public void testHeadsUp_disabledNotificationShade() {
+ public void testSuppressHeadsUp_disabledNotificationShade() {
Notification n = new Notification.Builder(getContext(), "a").build();
NotificationEntry entry = new NotificationEntryBuilder()
.setPkg("a")
@@ -147,8 +160,39 @@
false /* animate */);
TestableLooper.get(this).processAllMessages();
- assertFalse("The panel shouldn't allow heads up while notitifcation shade disabled",
- mStatusBarNotificationPresenter.canHeadsUp(entry, entry.getSbn()));
+ assertTrue("The panel should suppress interruptions while notification shade "
+ + "disabled",
+ mInterruptSuppressor.suppressAwakeHeadsUp(entry));
+ }
+
+ @Test
+ public void testSuppressInterruptions_vrMode() {
+ Notification n = new Notification.Builder(getContext(), "a").build();
+ NotificationEntry entry = new NotificationEntryBuilder()
+ .setPkg("a")
+ .setOpPkg("a")
+ .setTag("a")
+ .setNotification(n)
+ .build();
+ mStatusBarNotificationPresenter.mVrMode = true;
+
+ assertTrue("Vr mode should suppress interruptions",
+ mInterruptSuppressor.suppressAwakeInterruptions(entry));
+ }
+
+ @Test
+ public void testSuppressInterruptions_statusBarAlertsDisabled() {
+ Notification n = new Notification.Builder(getContext(), "a").build();
+ NotificationEntry entry = new NotificationEntryBuilder()
+ .setPkg("a")
+ .setOpPkg("a")
+ .setTag("a")
+ .setNotification(n)
+ .build();
+ when(mStatusBar.areNotificationAlertsDisabled()).thenReturn(true);
+
+ assertTrue("StatusBar alerts disabled shouldn't allow interruptions",
+ mInterruptSuppressor.suppressInterruptions(entry));
}
@Test
@@ -172,4 +216,3 @@
}
}
}
-
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index e407927..679ac22 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -42,7 +42,7 @@
import android.app.StatusBarManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
-import android.content.Context;
+import android.content.ContentResolver;
import android.content.IntentFilter;
import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.fingerprint.FingerprintManager;
@@ -109,18 +109,18 @@
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.init.NotificationsController;
+import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.interruption.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.logging.NotificationPanelLoggerFake;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -130,6 +130,7 @@
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
@@ -161,7 +162,7 @@
private StatusBar mStatusBar;
private FakeMetricsLogger mMetricsLogger;
private PowerManager mPowerManager;
- private TestableNotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+ private TestableNotificationInterruptStateProviderImpl mNotificationInterruptStateProvider;
@Mock private NotificationsController mNotificationsController;
@Mock private LightBarController mLightBarController;
@@ -179,7 +180,6 @@
@Mock private DozeScrimController mDozeScrimController;
@Mock private Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
@Mock private BiometricUnlockController mBiometricUnlockController;
- @Mock private NotificationInterruptionStateProvider.HeadsUpSuppressor mHeadsUpSuppressor;
@Mock private VisualStabilityManager mVisualStabilityManager;
@Mock private NotificationListener mNotificationListener;
@Mock private KeyguardViewMediator mKeyguardViewMediator;
@@ -193,9 +193,9 @@
@Mock private NotificationEntryListener mEntryListener;
@Mock private NotificationFilter mNotificationFilter;
@Mock private NotificationAlertingManager mNotificationAlertingManager;
+ @Mock private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
@Mock private NotificationLogger.ExpansionStateLogger mExpansionStateLogger;
@Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- @Mock private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
@Mock private NotificationShadeWindowView mNotificationShadeWindowView;
@Mock private BroadcastDispatcher mBroadcastDispatcher;
@Mock private AssistManager mAssistManager;
@@ -263,10 +263,12 @@
mPowerManager = new PowerManager(mContext, powerManagerService, thermalService,
Handler.createAsync(Looper.myLooper()));
- mNotificationInterruptionStateProvider =
- new TestableNotificationInterruptionStateProvider(mContext, mPowerManager,
+ mNotificationInterruptStateProvider =
+ new TestableNotificationInterruptStateProviderImpl(mContext.getContentResolver(),
+ mPowerManager,
mDreamManager, mAmbientDisplayConfiguration, mNotificationFilter,
- mStatusBarStateController, mBatteryController);
+ mStatusBarStateController, mBatteryController, mHeadsUpManager,
+ new Handler(TestableLooper.get(this).getLooper()));
mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class));
mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class));
@@ -299,9 +301,6 @@
return null;
}).when(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(any());
- mNotificationInterruptionStateProvider.setUpWithPresenter(mNotificationPresenter,
- mHeadsUpManager, mHeadsUpSuppressor);
-
when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
WakefulnessLifecycle wakefulnessLifecycle = new WakefulnessLifecycle();
@@ -348,7 +347,7 @@
),
mNotificationGutsManager,
notificationLogger,
- mNotificationInterruptionStateProvider,
+ mNotificationInterruptStateProvider,
mNotificationViewHierarchyManager,
mKeyguardViewMediator,
mNotificationAlertingManager,
@@ -562,7 +561,6 @@
when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
when(mNotificationFilter.shouldFilterOut(any())).thenReturn(false);
when(mDreamManager.isDreaming()).thenReturn(false);
- when(mHeadsUpSuppressor.canHeadsUp(any(), any())).thenReturn(true);
Notification n = new Notification.Builder(getContext(), "a")
.setGroup("a")
@@ -578,7 +576,7 @@
.setImportance(IMPORTANCE_HIGH)
.build();
- assertTrue(mNotificationInterruptionStateProvider.shouldHeadsUp(entry));
+ assertTrue(mNotificationInterruptStateProvider.shouldHeadsUp(entry));
}
@Test
@@ -587,7 +585,6 @@
when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
when(mNotificationFilter.shouldFilterOut(any())).thenReturn(false);
when(mDreamManager.isDreaming()).thenReturn(false);
- when(mHeadsUpSuppressor.canHeadsUp(any(), any())).thenReturn(true);
Notification n = new Notification.Builder(getContext(), "a")
.setGroup("a")
@@ -603,7 +600,7 @@
.setImportance(IMPORTANCE_HIGH)
.build();
- assertFalse(mNotificationInterruptionStateProvider.shouldHeadsUp(entry));
+ assertFalse(mNotificationInterruptStateProvider.shouldHeadsUp(entry));
}
@Test
@@ -612,7 +609,6 @@
when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
when(mNotificationFilter.shouldFilterOut(any())).thenReturn(false);
when(mDreamManager.isDreaming()).thenReturn(false);
- when(mHeadsUpSuppressor.canHeadsUp(any(), any())).thenReturn(true);
Notification n = new Notification.Builder(getContext(), "a").build();
@@ -625,7 +621,7 @@
.setSuppressedVisualEffects(SUPPRESSED_EFFECT_PEEK)
.build();
- assertFalse(mNotificationInterruptionStateProvider.shouldHeadsUp(entry));
+ assertFalse(mNotificationInterruptStateProvider.shouldHeadsUp(entry));
}
@Test
@@ -634,7 +630,6 @@
when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
when(mNotificationFilter.shouldFilterOut(any())).thenReturn(false);
when(mDreamManager.isDreaming()).thenReturn(false);
- when(mHeadsUpSuppressor.canHeadsUp(any(), any())).thenReturn(true);
Notification n = new Notification.Builder(getContext(), "a").build();
@@ -646,7 +641,7 @@
.setImportance(IMPORTANCE_HIGH)
.build();
- assertTrue(mNotificationInterruptionStateProvider.shouldHeadsUp(entry));
+ assertTrue(mNotificationInterruptStateProvider.shouldHeadsUp(entry));
}
@Test
@@ -872,19 +867,21 @@
verify(mDozeServiceHost).setDozeSuppressed(false);
}
- public static class TestableNotificationInterruptionStateProvider extends
- NotificationInterruptionStateProvider {
+ public static class TestableNotificationInterruptStateProviderImpl extends
+ NotificationInterruptStateProviderImpl {
- TestableNotificationInterruptionStateProvider(
- Context context,
+ TestableNotificationInterruptStateProviderImpl(
+ ContentResolver contentResolver,
PowerManager powerManager,
IDreamManager dreamManager,
AmbientDisplayConfiguration ambientDisplayConfiguration,
NotificationFilter filter,
StatusBarStateController controller,
- BatteryController batteryController) {
- super(context, powerManager, dreamManager, ambientDisplayConfiguration, filter,
- batteryController, controller);
+ BatteryController batteryController,
+ HeadsUpManager headsUpManager,
+ Handler mainHandler) {
+ super(contentResolver, powerManager, dreamManager, ambientDisplayConfiguration, filter,
+ batteryController, controller, headsUpManager, mainHandler);
mUseHeadsUp = true;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index a0d551c..cddbb9f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -207,7 +207,7 @@
protected void setupNetworkController() {
// For now just pretend to be the data sim, so we can test that too.
mSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
- when(mMockTm.isDataConnectionEnabled()).thenReturn(true);
+ when(mMockTm.isDataConnectionAllowed()).thenReturn(true);
setDefaultSubId(mSubId);
setSubscriptions(mSubId);
mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId);
@@ -235,7 +235,7 @@
subs.add(subscription);
}
when(mMockSm.getActiveSubscriptionInfoList()).thenReturn(subs);
- when(mMockSm.getActiveAndHiddenSubscriptionInfoList()).thenReturn(subs);
+ when(mMockSm.getCompleteActiveSubscriptionInfoList()).thenReturn(subs);
mNetworkController.doUpdateMobileControllers();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 3eb0c44..d8b6aac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -119,7 +119,7 @@
@Test
public void testNoInternetIcon_withDefaultSub() {
setupNetworkController();
- when(mMockTm.isDataConnectionEnabled()).thenReturn(false);
+ when(mMockTm.isDataConnectionAllowed()).thenReturn(false);
setupDefaultSignal();
updateDataConnectionState(TelephonyManager.DATA_CONNECTED, 0);
setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
@@ -133,7 +133,7 @@
@Test
public void testDataDisabledIcon_withDefaultSub() {
setupNetworkController();
- when(mMockTm.isDataConnectionEnabled()).thenReturn(false);
+ when(mMockTm.isDataConnectionAllowed()).thenReturn(false);
setupDefaultSignal();
updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
@@ -147,7 +147,7 @@
@Test
public void testNonDefaultSIM_showsFullSignal_connected() {
setupNetworkController();
- when(mMockTm.isDataConnectionEnabled()).thenReturn(false);
+ when(mMockTm.isDataConnectionAllowed()).thenReturn(false);
setupDefaultSignal();
setDefaultSubId(mSubId + 1);
updateDataConnectionState(TelephonyManager.DATA_CONNECTED, 0);
@@ -162,7 +162,7 @@
@Test
public void testNonDefaultSIM_showsFullSignal_disconnected() {
setupNetworkController();
- when(mMockTm.isDataConnectionEnabled()).thenReturn(false);
+ when(mMockTm.isDataConnectionAllowed()).thenReturn(false);
setupDefaultSignal();
setDefaultSubId(mSubId + 1);
updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
@@ -177,7 +177,7 @@
@Test
public void testDataDisabledIcon_UserNotSetup() {
setupNetworkController();
- when(mMockTm.isDataConnectionEnabled()).thenReturn(false);
+ when(mMockTm.isDataConnectionAllowed()).thenReturn(false);
setupDefaultSignal();
updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
@@ -192,7 +192,7 @@
@Test
public void testAlwaysShowDataRatIcon() {
setupDefaultSignal();
- when(mMockTm.isDataConnectionEnabled()).thenReturn(false);
+ when(mMockTm.isDataConnectionAllowed()).thenReturn(false);
updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED,
TelephonyManager.NETWORK_TYPE_GSM);
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 538082d..8265009 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -18,6 +18,7 @@
import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
+import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE;
import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
import static android.view.autofill.AutofillManager.ACTION_RESPONSE_EXPIRED;
import static android.view.autofill.AutofillManager.ACTION_START_SESSION;
@@ -624,7 +625,7 @@
+ ", flags=" + flags + ")");
}
mForAugmentedAutofillOnly = true;
- triggerAugmentedAutofillLocked();
+ triggerAugmentedAutofillLocked(flags);
return;
}
@@ -834,7 +835,7 @@
}
// Although "standard" autofill is disabled, it might still trigger augmented autofill
- if (triggerAugmentedAutofillLocked() != null) {
+ if (triggerAugmentedAutofillLocked(requestFlags) != null) {
mForAugmentedAutofillOnly = true;
if (sDebug) {
Slog.d(TAG, "Service disabled autofill for " + mComponentName
@@ -2465,7 +2466,7 @@
// triggered augmented autofill
if (!isSameViewEntered) {
if (sDebug) Slog.d(TAG, "trigger augmented autofill.");
- triggerAugmentedAutofillLocked();
+ triggerAugmentedAutofillLocked(flags);
} else {
if (sDebug) Slog.d(TAG, "skip augmented autofill for same view.");
}
@@ -2863,8 +2864,8 @@
// The default autofill service cannot fullfill the request, let's check if the augmented
// autofill service can.
- mAugmentedAutofillDestroyer = triggerAugmentedAutofillLocked();
- if (mAugmentedAutofillDestroyer == null) {
+ mAugmentedAutofillDestroyer = triggerAugmentedAutofillLocked(flags);
+ if (mAugmentedAutofillDestroyer == null && ((flags & FLAG_PASSWORD_INPUT_TYPE) == 0)) {
if (sVerbose) {
Slog.v(TAG, "canceling session " + id + " when service returned null and it cannot "
+ "be augmented. AutofillableIds: " + autofillableIds);
@@ -2874,8 +2875,14 @@
removeSelf();
} else {
if (sVerbose) {
- Slog.v(TAG, "keeping session " + id + " when service returned null but "
- + "it can be augmented. AutofillableIds: " + autofillableIds);
+ if ((flags & FLAG_PASSWORD_INPUT_TYPE) != 0) {
+ Slog.v(TAG, "keeping session " + id + " when service returned null and "
+ + "augmented service is disabled for password fields. "
+ + "AutofillableIds: " + autofillableIds);
+ } else {
+ Slog.v(TAG, "keeping session " + id + " when service returned null but "
+ + "it can be augmented. AutofillableIds: " + autofillableIds);
+ }
}
mAugmentedAutofillableIds = autofillableIds;
try {
@@ -2894,7 +2901,12 @@
// TODO(b/123099468): might need to call it in other places, like when the service returns a
// non-null response but without datasets (for example, just SaveInfo)
@GuardedBy("mLock")
- private Runnable triggerAugmentedAutofillLocked() {
+ private Runnable triggerAugmentedAutofillLocked(int flags) {
+ // (TODO: b/141703197) Fix later by passing info to service.
+ if ((flags & FLAG_PASSWORD_INPUT_TYPE) != 0) {
+ return null;
+ }
+
// Check if Smart Suggestions is supported...
final @SmartSuggestionMode int supportedModes = mService
.getSupportedSmartSuggestionModesLocked();
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 7840b19..9b04e79 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1672,7 +1672,7 @@
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
| Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
| Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
- intent.putExtra("time-zone", zone.getID());
+ intent.putExtra(Intent.EXTRA_TIMEZONE, zone.getID());
getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
}
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index acd4039..d814b9c 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -200,7 +200,7 @@
// time
private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
- private static final String FEATURE_ID = "LocationService";
+ private static final String ATTRIBUTION_TAG = "LocationService";
private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
@@ -246,7 +246,7 @@
private int mBatterySaverMode;
private LocationManagerService(Context context) {
- mContext = context.createFeatureContext(FEATURE_ID);
+ mContext = context.createAttributionContext(ATTRIBUTION_TAG);
mHandler = FgThread.getHandler();
mLocalService = new LocalService();
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 2cfe404..b464422 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -161,9 +161,6 @@
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
@@ -627,22 +624,17 @@
* @see #syncRequestsAsync
*/
private void syncRequests() {
- boolean syncRequired = false;
+ Set<String> packages = null;
synchronized (mLock) {
if (mIsPackagesReady) {
- Set<String> packages = getPackagesPendingHealthChecksLocked();
- if (!packages.equals(mRequestedHealthCheckPackages)) {
- syncRequired = true;
- mRequestedHealthCheckPackages = packages;
- }
+ packages = getPackagesPendingHealthChecksLocked();
} // else, we will sync requests when packages become ready
}
// Call outside lock to avoid holding lock when calling into the controller.
- if (syncRequired) {
- Slog.i(TAG, "Syncing health check requests for packages: "
- + mRequestedHealthCheckPackages);
- mHealthCheckController.syncRequests(mRequestedHealthCheckPackages);
+ if (packages != null) {
+ Slog.i(TAG, "Syncing health check requests for packages: " + packages);
+ mHealthCheckController.syncRequests(packages);
}
}
diff --git a/services/core/java/com/android/server/SensorNotificationService.java b/services/core/java/com/android/server/SensorNotificationService.java
index 9082dca..db3db0c 100644
--- a/services/core/java/com/android/server/SensorNotificationService.java
+++ b/services/core/java/com/android/server/SensorNotificationService.java
@@ -48,7 +48,7 @@
private static final long MILLIS_2010_1_1 = 1262358000000l;
- private static final String FEATURE_ID = "SensorNotificationService";
+ private static final String ATTRIBUTION_TAG = "SensorNotificationService";
private Context mContext;
private SensorManager mSensorManager;
@@ -59,7 +59,7 @@
private long mLocalGeomagneticFieldUpdateTime = -LOCATION_MIN_TIME;
public SensorNotificationService(Context context) {
- super(context.createFeatureContext(FEATURE_ID));
+ super(context.createAttributionContext(ATTRIBUTION_TAG));
mContext = getContext();
}
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index b43ae36..cfb79aa 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -100,7 +100,7 @@
@Nullable public final ComponentName component;
@UserIdInt public final int userId;
- private ServiceInfo(ResolveInfo resolveInfo, int currentUserId) {
+ ServiceInfo(ResolveInfo resolveInfo, int currentUserId) {
Preconditions.checkArgument(resolveInfo.serviceInfo.getComponentName() != null);
Bundle metadata = resolveInfo.serviceInfo.metaData;
@@ -316,6 +316,7 @@
}
mContext.unbindService(this);
+ onServiceDisconnected(mServiceInfo.component);
mServiceInfo = ServiceInfo.NONE;
}
@@ -339,15 +340,13 @@
@Override
public final void onServiceConnected(ComponentName component, IBinder binder) {
Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
+ Preconditions.checkState(mBinder == null);
if (D) {
Log.i(TAG, getLogPrefix() + " connected to " + component.toShortString());
}
mBinder = binder;
-
- // we always run the on bind callback even if we know that the binder is dead already so
- // that there are always balance pairs of bind/unbind callbacks
if (mOnBind != null) {
try {
mOnBind.run(binder);
@@ -357,19 +356,16 @@
Log.e(TAG, getLogPrefix() + " exception running on " + mServiceInfo, e);
}
}
-
- try {
- // setting the binder to null lets us skip queued transactions
- binder.linkToDeath(() -> mBinder = null, 0);
- } catch (RemoteException e) {
- mBinder = null;
- }
}
@Override
public final void onServiceDisconnected(ComponentName component) {
Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
+ if (mBinder == null) {
+ return;
+ }
+
if (D) {
Log.i(TAG, getLogPrefix() + " disconnected from " + component.toShortString());
}
@@ -391,18 +387,18 @@
onBestServiceChanged(true);
}
- private void onUserSwitched(@UserIdInt int userId) {
+ void onUserSwitched(@UserIdInt int userId) {
mCurrentUserId = userId;
onBestServiceChanged(false);
}
- private void onUserUnlocked(@UserIdInt int userId) {
+ void onUserUnlocked(@UserIdInt int userId) {
if (userId == mCurrentUserId) {
onBestServiceChanged(false);
}
}
- private void onPackageChanged(String packageName) {
+ void onPackageChanged(String packageName) {
// force a rebind if the changed package was the currently connected package
String currentPackageName =
mServiceInfo.component != null ? mServiceInfo.component.getPackageName() : null;
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 7c833fa..12a1a95 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -75,7 +75,9 @@
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -293,7 +295,7 @@
public void onChange(boolean selfChange, Uri uri) {
synchronized (mLock) {
// setup wizard is done now so we can unblock
- if (setupWizardCompleteForCurrentUser()) {
+ if (setupWizardCompleteForCurrentUser() && !selfChange) {
mSetupWizardComplete = true;
getContext().getContentResolver()
.unregisterContentObserver(mSetupWizardObserver);
@@ -348,6 +350,9 @@
IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
context.registerReceiver(mBatteryReceiver, batteryFilter);
+ context.registerReceiver(mSettingsRestored,
+ new IntentFilter(Intent.ACTION_SETTING_RESTORED), null, mHandler);
+
mLocalPowerManager =
LocalServices.getService(PowerManagerInternal.class);
initPowerSave();
@@ -395,6 +400,22 @@
mHandler.post(() -> updateSystemProperties());
}
+ private final BroadcastReceiver mSettingsRestored = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ List<String> settings = Arrays.asList(
+ Secure.UI_NIGHT_MODE, Secure.DARK_THEME_CUSTOM_START_TIME,
+ Secure.DARK_THEME_CUSTOM_END_TIME);
+ if (settings.contains(intent.getExtras().getCharSequence(Intent.EXTRA_SETTING_NAME))) {
+ synchronized (mLock) {
+ updateNightModeFromSettingsLocked(context, context.getResources(),
+ UserHandle.getCallingUserId());
+ updateConfigurationLocked();
+ }
+ }
+ }
+ };
+
private void initPowerSave() {
mPowerSave =
mLocalPowerManager.getLowPowerState(ServiceType.NIGHT_MODE)
@@ -1297,9 +1318,9 @@
if (Sandman.shouldStartDockApp(getContext(), homeIntent)) {
try {
int result = ActivityTaskManager.getService().startActivityWithConfig(
- null, getContext().getBasePackageName(), getContext().getFeatureId(),
- homeIntent, null, null, null, 0, 0, mConfiguration, null,
- UserHandle.USER_CURRENT);
+ null, getContext().getBasePackageName(),
+ getContext().getAttributionTag(), homeIntent, null, null, null, 0, 0,
+ mConfiguration, null, UserHandle.USER_CURRENT);
if (ActivityManager.isStartResultSuccessful(result)) {
dockAppStarted = true;
} else if (result != ActivityManager.START_INTENT_NOT_RESOLVED) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 59f64ac..8f5fbf7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2931,25 +2931,35 @@
final PlatformCompat platformCompat = (PlatformCompat)
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
String toggleValue = getNextArgRequired();
- if (toggleValue.equals("reset-all")) {
- final String packageName = getNextArgRequired();
- pw.println("Reset all changes for " + packageName + " to default value.");
- platformCompat.clearOverrides(packageName);
- return 0;
- }
- long changeId;
- String changeIdString = getNextArgRequired();
- try {
- changeId = Long.parseLong(changeIdString);
- } catch (NumberFormatException e) {
- changeId = platformCompat.lookupChangeId(changeIdString);
- }
- if (changeId == -1) {
- pw.println("Unknown or invalid change: '" + changeIdString + "'.");
- return -1;
+ boolean toggleAll = false;
+ int targetSdkVersion = -1;
+ long changeId = -1;
+
+ if (toggleValue.endsWith("-all")) {
+ toggleValue = toggleValue.substring(0, toggleValue.lastIndexOf("-all"));
+ toggleAll = true;
+ if (!toggleValue.equals("reset")) {
+ try {
+ targetSdkVersion = Integer.parseInt(getNextArgRequired());
+ } catch (NumberFormatException e) {
+ pw.println("Invalid targetSdkVersion!");
+ return -1;
+ }
+ }
+ } else {
+ String changeIdString = getNextArgRequired();
+ try {
+ changeId = Long.parseLong(changeIdString);
+ } catch (NumberFormatException e) {
+ changeId = platformCompat.lookupChangeId(changeIdString);
+ }
+ if (changeId == -1) {
+ pw.println("Unknown or invalid change: '" + changeIdString + "'.");
+ return -1;
+ }
}
String packageName = getNextArgRequired();
- if (!platformCompat.isKnownChangeId(changeId)) {
+ if (!toggleAll && !platformCompat.isKnownChangeId(changeId)) {
pw.println("Warning! Change " + changeId + " is not known yet. Enabling/disabling it"
+ " could have no effect.");
}
@@ -2958,22 +2968,49 @@
try {
switch (toggleValue) {
case "enable":
- enabled.add(changeId);
- CompatibilityChangeConfig overrides =
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled));
- platformCompat.setOverrides(overrides, packageName);
- pw.println("Enabled change " + changeId + " for " + packageName + ".");
+ if (toggleAll) {
+ int numChanges = platformCompat.enableTargetSdkChanges(packageName,
+ targetSdkVersion);
+ if (numChanges == 0) {
+ pw.println("No changes were enabled.");
+ return -1;
+ }
+ pw.println("Enabled " + numChanges + " changes gated by targetSdkVersion "
+ + targetSdkVersion + " for " + packageName + ".");
+ } else {
+ enabled.add(changeId);
+ CompatibilityChangeConfig overrides =
+ new CompatibilityChangeConfig(
+ new Compatibility.ChangeConfig(enabled, disabled));
+ platformCompat.setOverrides(overrides, packageName);
+ pw.println("Enabled change " + changeId + " for " + packageName + ".");
+ }
return 0;
case "disable":
- disabled.add(changeId);
- overrides =
- new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabled, disabled));
- platformCompat.setOverrides(overrides, packageName);
- pw.println("Disabled change " + changeId + " for " + packageName + ".");
+ if (toggleAll) {
+ int numChanges = platformCompat.disableTargetSdkChanges(packageName,
+ targetSdkVersion);
+ if (numChanges == 0) {
+ pw.println("No changes were disabled.");
+ return -1;
+ }
+ pw.println("Disabled " + numChanges + " changes gated by targetSdkVersion "
+ + targetSdkVersion + " for " + packageName + ".");
+ } else {
+ disabled.add(changeId);
+ CompatibilityChangeConfig overrides =
+ new CompatibilityChangeConfig(
+ new Compatibility.ChangeConfig(enabled, disabled));
+ platformCompat.setOverrides(overrides, packageName);
+ pw.println("Disabled change " + changeId + " for " + packageName + ".");
+ }
return 0;
case "reset":
+ if (toggleAll) {
+ platformCompat.clearOverrides(packageName);
+ pw.println("Reset all changes for " + packageName + " to default value.");
+ return 0;
+ }
if (platformCompat.clearOverride(changeId, packageName)) {
pw.println("Reset change " + changeId + " for " + packageName
+ " to default value.");
@@ -3304,6 +3341,8 @@
pw.println(" enable|disable|reset <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
pw.println(" Toggles a change either by id or by name for <PACKAGE_NAME>.");
pw.println(" It kills <PACKAGE_NAME> (to allow the toggle to take effect).");
+ pw.println(" enable-all|disable-all <targetSdkVersion> <PACKAGE_NAME");
+ pw.println(" Toggles all changes that are gated by <targetSdkVersion>.");
pw.println(" reset-all <PACKAGE_NAME>");
pw.println(" Removes all existing overrides for all changes for ");
pw.println(" <PACKAGE_NAME> (back to default behaviour).");
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 6b16513..0e9970e 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -61,6 +61,7 @@
import android.app.IApplicationThread;
import android.app.IUidObserver;
import android.compat.annotation.ChangeId;
+import android.compat.annotation.Disabled;
import android.compat.annotation.EnabledAfter;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -70,6 +71,7 @@
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;
@@ -345,6 +347,14 @@
private static final long NATIVE_HEAP_POINTER_TAGGING = 135754954; // This is a bug id.
/**
+ * Enable sampled memory bug detection in the app.
+ * @see <a href="https://source.android.com/devices/tech/debug/gwp-asan">GWP-ASan</a>.
+ */
+ @ChangeId
+ @Disabled
+ private static final long GWP_ASAN = 135634846; // This is a bug id.
+
+ /**
* Apps have no access to the private data directories of any other app, even if the other
* app has made them world-readable.
*/
@@ -1634,6 +1644,28 @@
return gidArray;
}
+ private int decideGwpAsanLevel(ProcessRecord app) {
+ // Look at the process attribute first.
+ if (app.processInfo != null && app.processInfo.enableGwpAsan != null) {
+ return app.processInfo.enableGwpAsan ? Zygote.GWP_ASAN_LEVEL_ALWAYS
+ : Zygote.GWP_ASAN_LEVEL_NEVER;
+ }
+ // Then at the applicaton attribute.
+ if (app.info.isGwpAsanEnabled() != null) {
+ return app.info.isGwpAsanEnabled() ? Zygote.GWP_ASAN_LEVEL_ALWAYS
+ : Zygote.GWP_ASAN_LEVEL_NEVER;
+ }
+ // If the app does not specify enableGwpAsan, the default behavior is lottery among the
+ // system apps, and disabled for user apps, unless overwritten by the compat feature.
+ if (mPlatformCompat.isChangeEnabled(GWP_ASAN, app.info)) {
+ return Zygote.GWP_ASAN_LEVEL_ALWAYS;
+ }
+ if ((app.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ return Zygote.GWP_ASAN_LEVEL_LOTTERY;
+ }
+ return Zygote.GWP_ASAN_LEVEL_NEVER;
+ }
+
/**
* @return {@code true} if process start is successful, false otherwise.
*/
@@ -1803,6 +1835,8 @@
runtimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
}
+ runtimeFlags |= decideGwpAsanLevel(app);
+
String invokeWith = null;
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
// Debuggable apps may include a wrapper script with their library directory.
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index c029811..a78caac 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -384,6 +384,9 @@
pw.println(processInfo.deniedPermissions.valueAt(i));
}
}
+ if (processInfo.enableGwpAsan != null) {
+ pw.print(prefix); pw.println(" enableGwpAsan=" + processInfo.enableGwpAsan);
+ }
}
pw.print(prefix); pw.print("mRequiredAbi="); pw.print(mRequiredAbi);
pw.print(" instructionSet="); pw.println(instructionSet);
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 471c97b..310664e 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -19,8 +19,8 @@
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
-import static android.app.AppOpsManager.CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE;
-import static android.app.AppOpsManager.FILTER_BY_FEATURE_ID;
+import static android.app.AppOpsManager.CALL_BACK_ON_SWITCHED_OP;
+import static android.app.AppOpsManager.FILTER_BY_ATTRIBUTION_TAG;
import static android.app.AppOpsManager.FILTER_BY_OP_NAMES;
import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME;
import static android.app.AppOpsManager.FILTER_BY_UID;
@@ -80,14 +80,13 @@
import android.app.AppOpsManager.HistoricalOps;
import android.app.AppOpsManager.Mode;
import android.app.AppOpsManager.OpEntry;
-import android.app.AppOpsManager.OpFeatureEntry;
+import android.app.AppOpsManager.AttributedOpEntry;
import android.app.AppOpsManager.OpFlags;
import android.app.AppOpsManagerInternal;
import android.app.AppOpsManagerInternal.CheckOpsDelegate;
import android.app.AsyncNotedAppOp;
import android.app.RuntimeAppOpAccessMessage;
import android.app.SyncNotedAppOp;
-import android.compat.Compatibility;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -98,7 +97,7 @@
import android.content.pm.PackageManagerInternal;
import android.content.pm.PermissionInfo;
import android.content.pm.UserInfo;
-import android.content.pm.parsing.component.ParsedFeature;
+import android.content.pm.parsing.component.ParsedAttribution;
import android.database.ContentObserver;
import android.hardware.camera2.CameraDevice.CAMERA_AUDIO_RESTRICTION;
import android.net.Uri;
@@ -372,14 +371,14 @@
}
OpEventProxyInfo acquire(@IntRange(from = 0) int uid, @Nullable String packageName,
- @Nullable String featureId) {
+ @Nullable String attributionTag) {
OpEventProxyInfo recycled = acquire();
if (recycled != null) {
- recycled.reinit(uid, packageName, featureId);
+ recycled.reinit(uid, packageName, attributionTag);
return recycled;
}
- return new OpEventProxyInfo(uid, packageName, featureId);
+ return new OpEventProxyInfo(uid, packageName, attributionTag);
}
}
@@ -672,8 +671,8 @@
*/
@Nullable RestrictionBypass bypass;
- /** Lazily populated cache of featureIds of this package */
- final @NonNull ArraySet<String> knownFeatureIds = new ArraySet<>();
+ /** Lazily populated cache of attributionTags of this package */
+ final @NonNull ArraySet<String> knownAttributionTags = new ArraySet<>();
Ops(String _packageName, UidState _uidState) {
packageName = _packageName;
@@ -777,8 +776,8 @@
}
}
- private final class FeatureOp {
- public final @Nullable String featureId;
+ private final class AttributedOp {
+ public final @Nullable String tag;
public final @NonNull Op parent;
/**
@@ -805,8 +804,8 @@
@GuardedBy("AppOpsService.this")
private @Nullable ArrayMap<IBinder, InProgressStartOpEvent> mInProgressEvents;
- FeatureOp(@Nullable String featureId, @NonNull Op parent) {
- this.featureId = featureId;
+ AttributedOp(@Nullable String tag, @NonNull Op parent) {
+ this.tag = tag;
this.parent = parent;
}
@@ -815,18 +814,18 @@
*
* @param proxyUid The uid of the proxy
* @param proxyPackageName The package name of the proxy
- * @param proxyFeatureId the featureId in the proxies package
+ * @param proxyAttributionTag the attributionTag in the proxies package
* @param uidState UID state of the app noteOp/startOp was called for
* @param flags OpFlags of the call
*/
public void accessed(int proxyUid, @Nullable String proxyPackageName,
- @Nullable String proxyFeatureId, @AppOpsManager.UidState int uidState,
+ @Nullable String proxyAttributionTag, @AppOpsManager.UidState int uidState,
@OpFlags int flags) {
accessed(System.currentTimeMillis(), -1, proxyUid, proxyPackageName,
- proxyFeatureId, uidState, flags);
+ proxyAttributionTag, uidState, flags);
mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, parent.packageName,
- featureId, uidState, flags);
+ tag, uidState, flags);
}
/**
@@ -836,12 +835,12 @@
* @param duration The duration of the event
* @param proxyUid The uid of the proxy
* @param proxyPackageName The package name of the proxy
- * @param proxyFeatureId the featureId in the proxies package
+ * @param proxyAttributionTag the attributionTag in the proxies package
* @param uidState UID state of the app noteOp/startOp was called for
* @param flags OpFlags of the call
*/
public void accessed(long noteTime, long duration, int proxyUid,
- @Nullable String proxyPackageName, @Nullable String proxyFeatureId,
+ @Nullable String proxyPackageName, @Nullable String proxyAttributionTag,
@AppOpsManager.UidState int uidState, @OpFlags int flags) {
long key = makeKey(uidState, flags);
@@ -852,7 +851,7 @@
OpEventProxyInfo proxyInfo = null;
if (proxyUid != Process.INVALID_UID) {
proxyInfo = mOpEventProxyInfoPool.acquire(proxyUid, proxyPackageName,
- proxyFeatureId);
+ proxyAttributionTag);
}
NoteOpEvent existingEvent = mAccessEvents.get(key);
@@ -873,7 +872,7 @@
rejected(System.currentTimeMillis(), uidState, flags);
mHistoricalRegistry.incrementOpRejected(parent.op, parent.uid, parent.packageName,
- featureId, uidState, flags);
+ tag, uidState, flags);
}
/**
@@ -939,7 +938,7 @@
// startOp events don't support proxy, hence use flags==SELF
mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, parent.packageName,
- featureId, uidState, OP_FLAG_SELF);
+ tag, uidState, OP_FLAG_SELF);
}
/**
@@ -979,7 +978,7 @@
mAccessEvents.put(makeKey(event.getUidState(), OP_FLAG_SELF), finishedEvent);
mHistoricalRegistry.increaseOpAccessDuration(parent.op, parent.uid,
- parent.packageName, featureId, event.getUidState(),
+ parent.packageName, tag, event.getUidState(),
AppOpsManager.OP_FLAG_SELF, finishedEvent.getDuration());
mInProgressStartOpEventPool.release(event);
@@ -987,7 +986,7 @@
if (mInProgressEvents.isEmpty()) {
mInProgressEvents = null;
- // TODO moltmann: Also callback for single feature activity changes
+ // TODO moltmann: Also callback for single attribution tag activity changes
if (triggerCallbackIfNeeded && !parent.isRunning()) {
scheduleOpActiveChangedIfNeededLocked(parent.op, parent.uid,
parent.packageName, false);
@@ -1078,14 +1077,14 @@
}
/**
- * Add all data from the {@code featureToAdd} to this op.
+ * Add all data from the {@code opToAdd} to this op.
*
* <p>If there is an event for the same key in both the later event is retained.
* <p>{@code opToAdd} should not be used after this method is called.
*
* @param opToAdd The op to add
*/
- public void add(@NonNull FeatureOp opToAdd) {
+ public void add(@NonNull AttributedOp opToAdd) {
if (opToAdd.mInProgressEvents != null) {
Slog.w(TAG, "Ignoring " + opToAdd.mInProgressEvents.size() + " running app-ops");
@@ -1129,7 +1128,7 @@
return clone;
}
- @NonNull OpFeatureEntry createFeatureEntryLocked() {
+ @NonNull AttributedOpEntry createAttributedOpEntryLocked() {
LongSparseArray<NoteOpEvent> accessEvents = deepClone(mAccessEvents);
// Add in progress events as access events
@@ -1153,7 +1152,7 @@
LongSparseArray<NoteOpEvent> rejectEvents = deepClone(mRejectEvents);
- return new OpFeatureEntry(parent.op, isRunning(), accessEvents, rejectEvents);
+ return new AttributedOpEntry(parent.op, isRunning(), accessEvents, rejectEvents);
}
}
@@ -1165,8 +1164,8 @@
private @Mode int mode;
- /** featureId -> FeatureOp */
- final ArrayMap<String, FeatureOp> mFeatures = new ArrayMap<>(1);
+ /** attributionTag -> AttributedOp */
+ final ArrayMap<String, AttributedOp> mAttributions = new ArrayMap<>(1);
Op(UidState uidState, String packageName, int op, int uid) {
this.op = op;
@@ -1184,58 +1183,59 @@
return uidState.evalMode(op, mode);
}
- void removeFeaturesWithNoTime() {
- for (int i = mFeatures.size() - 1; i >= 0; i--) {
- if (!mFeatures.valueAt(i).hasAnyTime()) {
- mFeatures.removeAt(i);
+ void removeAttributionsWithNoTime() {
+ for (int i = mAttributions.size() - 1; i >= 0; i--) {
+ if (!mAttributions.valueAt(i).hasAnyTime()) {
+ mAttributions.removeAt(i);
}
}
}
- private @NonNull FeatureOp getOrCreateFeature(@NonNull Op parent,
- @Nullable String featureId) {
- FeatureOp featureOp;
+ private @NonNull AttributedOp getOrCreateAttribution(@NonNull Op parent,
+ @Nullable String attributionTag) {
+ AttributedOp attributedOp;
- featureOp = mFeatures.get(featureId);
- if (featureOp == null) {
- featureOp = new FeatureOp(featureId, parent);
- mFeatures.put(featureId, featureOp);
+ attributedOp = mAttributions.get(attributionTag);
+ if (attributedOp == null) {
+ attributedOp = new AttributedOp(attributionTag, parent);
+ mAttributions.put(attributionTag, attributedOp);
}
- return featureOp;
+ return attributedOp;
}
@NonNull OpEntry createEntryLocked() {
- final int numFeatures = mFeatures.size();
+ final int numAttributions = mAttributions.size();
- final ArrayMap<String, OpFeatureEntry> featureEntries = new ArrayMap<>(numFeatures);
- for (int i = 0; i < numFeatures; i++) {
- featureEntries.put(mFeatures.keyAt(i),
- mFeatures.valueAt(i).createFeatureEntryLocked());
+ final ArrayMap<String, AppOpsManager.AttributedOpEntry> attributionEntries =
+ new ArrayMap<>(numAttributions);
+ for (int i = 0; i < numAttributions; i++) {
+ attributionEntries.put(mAttributions.keyAt(i),
+ mAttributions.valueAt(i).createAttributedOpEntryLocked());
}
- return new OpEntry(op, mode, featureEntries);
+ return new OpEntry(op, mode, attributionEntries);
}
- @NonNull OpEntry createSingleFeatureEntryLocked(@Nullable String featureId) {
- final int numFeatures = mFeatures.size();
+ @NonNull OpEntry createSingleAttributionEntryLocked(@Nullable String attributionTag) {
+ final int numAttributions = mAttributions.size();
- final ArrayMap<String, OpFeatureEntry> featureEntries = new ArrayMap<>(1);
- for (int i = 0; i < numFeatures; i++) {
- if (Objects.equals(mFeatures.keyAt(i), featureId)) {
- featureEntries.put(mFeatures.keyAt(i),
- mFeatures.valueAt(i).createFeatureEntryLocked());
+ final ArrayMap<String, AttributedOpEntry> attributionEntries = new ArrayMap<>(1);
+ for (int i = 0; i < numAttributions; i++) {
+ if (Objects.equals(mAttributions.keyAt(i), attributionTag)) {
+ attributionEntries.put(mAttributions.keyAt(i),
+ mAttributions.valueAt(i).createAttributedOpEntryLocked());
break;
}
}
- return new OpEntry(op, mode, featureEntries);
+ return new OpEntry(op, mode, attributionEntries);
}
boolean isRunning() {
- final int numFeatures = mFeatures.size();
- for (int i = 0; i < numFeatures; i++) {
- if (mFeatures.valueAt(i).isRunning()) {
+ final int numAttributions = mAttributions.size();
+ for (int i = 0; i < numAttributions; i++) {
+ if (mAttributions.valueAt(i).isRunning()) {
return true;
}
}
@@ -1408,10 +1408,11 @@
}
/**
- * Call {@link FeatureOp#onClientDeath featureOp.onClientDeath(clientId)}.
+ * Call {@link AttributedOp#onClientDeath attributedOp.onClientDeath(clientId)}.
*/
- private static void onClientDeath(@NonNull FeatureOp featureOp, @NonNull IBinder clientId) {
- featureOp.onClientDeath(clientId);
+ private static void onClientDeath(@NonNull AttributedOp attributedOp,
+ @NonNull IBinder clientId) {
+ attributedOp.onClientDeath(clientId);
}
@@ -1493,20 +1494,21 @@
return;
}
- ArrayMap<String, String> dstFeatureIds = new ArrayMap<>();
- ArraySet<String> featureIds = new ArraySet<>();
- featureIds.add(null);
- if (pkg.getFeatures() != null) {
- int numFeatures = pkg.getFeatures().size();
- for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
- ParsedFeature feature = pkg.getFeatures().get(featureNum);
- featureIds.add(feature.id);
+ ArrayMap<String, String> dstAttributionTags = new ArrayMap<>();
+ ArraySet<String> attributionTags = new ArraySet<>();
+ attributionTags.add(null);
+ if (pkg.getAttributions() != null) {
+ int numAttributions = pkg.getAttributions().size();
+ for (int attributionNum = 0; attributionNum < numAttributions;
+ attributionNum++) {
+ ParsedAttribution attribution = pkg.getAttributions().get(attributionNum);
+ attributionTags.add(attribution.tag);
- int numInheritFrom = feature.inheritFrom.size();
+ int numInheritFrom = attribution.inheritFrom.size();
for (int inheritFromNum = 0; inheritFromNum < numInheritFrom;
inheritFromNum++) {
- dstFeatureIds.put(feature.inheritFrom.get(inheritFromNum),
- feature.id);
+ dstAttributionTags.put(attribution.inheritFrom.get(inheritFromNum),
+ attribution.tag);
}
}
}
@@ -1524,27 +1526,30 @@
// Reset cached package properties to re-initialize when needed
ops.bypass = null;
- ops.knownFeatureIds.clear();
+ ops.knownAttributionTags.clear();
- // Merge data collected for removed features into their successor features
+ // Merge data collected for removed attributions into their successor
+ // attributions
int numOps = ops.size();
for (int opNum = 0; opNum < numOps; opNum++) {
Op op = ops.valueAt(opNum);
- int numFeatures = op.mFeatures.size();
- for (int featureNum = numFeatures - 1; featureNum >= 0; featureNum--) {
- String featureId = op.mFeatures.keyAt(featureNum);
+ int numAttributions = op.mAttributions.size();
+ for (int attributionNum = numAttributions - 1; attributionNum >= 0;
+ attributionNum--) {
+ String attributionTag = op.mAttributions.keyAt(attributionNum);
- if (featureIds.contains(featureId)) {
- // feature still exist after upgrade
+ if (attributionTags.contains(attributionTag)) {
+ // attribution still exist after upgrade
continue;
}
- String newFeatureId = dstFeatureIds.get(featureId);
+ String newAttributionTag = dstAttributionTags.get(attributionTag);
- FeatureOp newFeatureOp = op.getOrCreateFeature(op, newFeatureId);
- newFeatureOp.add(op.mFeatures.valueAt(featureNum));
- op.mFeatures.removeAt(featureNum);
+ AttributedOp newAttributedOp = op.getOrCreateAttribution(op,
+ newAttributionTag);
+ newAttributedOp.add(op.mAttributions.valueAt(attributionNum));
+ op.mAttributions.removeAt(attributionNum);
scheduleFastWriteLocked();
}
@@ -1744,12 +1749,13 @@
for (int opNum = 0; opNum < numOps; opNum++) {
final Op op = ops.valueAt(opNum);
- final int numFeatures = op.mFeatures.size();
- for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
- FeatureOp featureOp = op.mFeatures.valueAt(featureNum);
+ final int numAttributions = op.mAttributions.size();
+ for (int attributionNum = 0; attributionNum < numAttributions;
+ attributionNum++) {
+ AttributedOp attributedOp = op.mAttributions.valueAt(attributionNum);
- while (featureOp.mInProgressEvents != null) {
- featureOp.finished(featureOp.mInProgressEvents.keyAt(0));
+ while (attributedOp.mInProgressEvents != null) {
+ attributedOp.finished(attributedOp.mInProgressEvents.keyAt(0));
}
}
}
@@ -1829,11 +1835,13 @@
for (int opNum = 0; opNum < numOps; opNum++) {
Op op = ops.valueAt(opNum);
- int numFeatures = op.mFeatures.size();
- for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
- FeatureOp featureOp = op.mFeatures.valueAt(featureNum);
+ int numAttributions = op.mAttributions.size();
+ for (int attributionNum = 0; attributionNum < numAttributions;
+ attributionNum++) {
+ AttributedOp attributedOp = op.mAttributions.valueAt(
+ attributionNum);
- featureOp.onUidStateChanged(newState);
+ attributedOp.onUidStateChanged(newState);
}
}
}
@@ -1979,9 +1987,9 @@
/**
* Verify that historical appop request arguments are valid.
*/
- private void ensureHistoricalOpRequestIsValid(int uid, String packageName, String featureId,
- List<String> opNames, int filter, long beginTimeMillis, long endTimeMillis,
- int flags) {
+ private void ensureHistoricalOpRequestIsValid(int uid, String packageName,
+ String attributionTag, List<String> opNames, int filter, long beginTimeMillis,
+ long endTimeMillis, int flags) {
if ((filter & FILTER_BY_UID) != 0) {
Preconditions.checkArgument(uid != Process.INVALID_UID);
} else {
@@ -1994,8 +2002,8 @@
Preconditions.checkArgument(packageName == null);
}
- if ((filter & FILTER_BY_FEATURE_ID) == 0) {
- Preconditions.checkArgument(featureId == null);
+ if ((filter & FILTER_BY_ATTRIBUTION_TAG) == 0) {
+ Preconditions.checkArgument(attributionTag == null);
}
if ((filter & FILTER_BY_OP_NAMES) != 0) {
@@ -2005,17 +2013,18 @@
}
Preconditions.checkFlagsArgument(filter,
- FILTER_BY_UID | FILTER_BY_PACKAGE_NAME | FILTER_BY_FEATURE_ID | FILTER_BY_OP_NAMES);
+ FILTER_BY_UID | FILTER_BY_PACKAGE_NAME | FILTER_BY_ATTRIBUTION_TAG
+ | FILTER_BY_OP_NAMES);
Preconditions.checkArgumentNonnegative(beginTimeMillis);
Preconditions.checkArgument(endTimeMillis > beginTimeMillis);
Preconditions.checkFlagsArgument(flags, OP_FLAGS_ALL);
}
@Override
- public void getHistoricalOps(int uid, String packageName, String featureId,
+ public void getHistoricalOps(int uid, String packageName, String attributionTag,
List<String> opNames, int filter, long beginTimeMillis, long endTimeMillis,
int flags, RemoteCallback callback) {
- ensureHistoricalOpRequestIsValid(uid, packageName, featureId, opNames, filter,
+ ensureHistoricalOpRequestIsValid(uid, packageName, attributionTag, opNames, filter,
beginTimeMillis, endTimeMillis, flags);
Objects.requireNonNull(callback, "callback cannot be null");
@@ -2036,15 +2045,15 @@
// Must not hold the appops lock
mHandler.post(PooledLambda.obtainRunnable(HistoricalRegistry::getHistoricalOps,
- mHistoricalRegistry, uid, packageName, featureId, opNamesArray, filter,
+ mHistoricalRegistry, uid, packageName, attributionTag, opNamesArray, filter,
beginTimeMillis, endTimeMillis, flags, callback).recycleOnUse());
}
@Override
- public void getHistoricalOpsFromDiskRaw(int uid, String packageName, String featureId,
+ public void getHistoricalOpsFromDiskRaw(int uid, String packageName, String attributionTag,
List<String> opNames, int filter, long beginTimeMillis, long endTimeMillis,
int flags, RemoteCallback callback) {
- ensureHistoricalOpRequestIsValid(uid, packageName, featureId, opNames, filter,
+ ensureHistoricalOpRequestIsValid(uid, packageName, attributionTag, opNames, filter,
beginTimeMillis, endTimeMillis, flags);
Objects.requireNonNull(callback, "callback cannot be null");
@@ -2056,7 +2065,7 @@
// Must not hold the appops lock
mHandler.post(PooledLambda.obtainRunnable(HistoricalRegistry::getHistoricalOpsFromDiskRaw,
- mHistoricalRegistry, uid, packageName, featureId, opNamesArray,
+ mHistoricalRegistry, uid, packageName, attributionTag, opNamesArray,
filter, beginTimeMillis, endTimeMillis, flags, callback).recycleOnUse());
}
@@ -2090,9 +2099,9 @@
}
private void pruneOpLocked(Op op, int uid, String packageName) {
- op.removeFeaturesWithNoTime();
+ op.removeAttributionsWithNoTime();
- if (op.mFeatures.size() == 0) {
+ if (op.mAttributions.isEmpty()) {
Ops ops = getOpsLocked(uid, packageName, null, null, false /* edit */);
if (ops != null) {
ops.remove(op.op);
@@ -2611,8 +2620,8 @@
callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
mPackageModeWatchers.get(packageName));
- curOp.removeFeaturesWithNoTime();
- if (curOp.mFeatures.size() == 0) {
+ curOp.removeAttributionsWithNoTime();
+ if (curOp.mAttributions.isEmpty()) {
pkgOps.removeAt(j);
}
}
@@ -2679,10 +2688,8 @@
synchronized (this) {
int switchOp = (op != AppOpsManager.OP_NONE) ? AppOpsManager.opToSwitch(op) : op;
- // See CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE
int notifiedOps;
- if (Compatibility.isChangeEnabled(
- CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE)) {
+ if ((flags & CALL_BACK_ON_SWITCHED_OP) == 0) {
if (op == OP_NONE) {
notifiedOps = ALL_OPS;
} else {
@@ -2898,8 +2905,8 @@
@Override
public int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
- String proxiedFeatureId, int proxyUid, String proxyPackageName,
- String proxyFeatureId, boolean shouldCollectAsyncNotedOp, String message) {
+ String proxiedAttributionTag, int proxyUid, String proxyPackageName,
+ String proxyAttributionTag, boolean shouldCollectAsyncNotedOp, String message) {
verifyIncomingUid(proxyUid);
verifyIncomingOp(code);
@@ -2915,7 +2922,7 @@
final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
final int proxyMode = noteOperationUnchecked(code, proxyUid, resolveProxyPackageName,
- proxyFeatureId, Process.INVALID_UID, null, null, proxyFlags,
+ proxyAttributionTag, Process.INVALID_UID, null, null, proxyFlags,
!isProxyTrusted, "proxy " + message);
if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
return proxyMode;
@@ -2928,27 +2935,27 @@
final int proxiedFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXIED
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXIED;
return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
- proxiedFeatureId, proxyUid, resolveProxyPackageName, proxyFeatureId,
+ proxiedAttributionTag, proxyUid, resolveProxyPackageName, proxyAttributionTag,
proxiedFlags, shouldCollectAsyncNotedOp, message);
}
@Override
- public int noteOperation(int code, int uid, String packageName, String featureId,
+ public int noteOperation(int code, int uid, String packageName, String attributionTag,
boolean shouldCollectAsyncNotedOp, String message) {
final CheckOpsDelegate delegate;
synchronized (this) {
delegate = mCheckOpsDelegate;
}
if (delegate == null) {
- return noteOperationImpl(code, uid, packageName, featureId, shouldCollectAsyncNotedOp,
- message);
+ return noteOperationImpl(code, uid, packageName, attributionTag,
+ shouldCollectAsyncNotedOp, message);
}
- return delegate.noteOperation(code, uid, packageName, featureId, shouldCollectAsyncNotedOp,
- message, AppOpsService.this::noteOperationImpl);
+ return delegate.noteOperation(code, uid, packageName, attributionTag,
+ shouldCollectAsyncNotedOp, message, AppOpsService.this::noteOperationImpl);
}
private int noteOperationImpl(int code, int uid, @Nullable String packageName,
- @Nullable String featureId, boolean shouldCollectAsyncNotedOp,
+ @Nullable String attributionTag, boolean shouldCollectAsyncNotedOp,
@Nullable String message) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
@@ -2956,25 +2963,26 @@
if (resolvedPackageName == null) {
return AppOpsManager.MODE_IGNORED;
}
- return noteOperationUnchecked(code, uid, resolvedPackageName, featureId,
+ return noteOperationUnchecked(code, uid, resolvedPackageName, attributionTag,
Process.INVALID_UID, null, null, AppOpsManager.OP_FLAG_SELF,
shouldCollectAsyncNotedOp, message);
}
private int noteOperationUnchecked(int code, int uid, @NonNull String packageName,
- @Nullable String featureId, int proxyUid, String proxyPackageName,
- @Nullable String proxyFeatureId, @OpFlags int flags, boolean shouldCollectAsyncNotedOp,
- @Nullable String message) {
+ @Nullable String attributionTag, int proxyUid, String proxyPackageName,
+ @Nullable String proxyAttributionTag, @OpFlags int flags,
+ boolean shouldCollectAsyncNotedOp, @Nullable String message) {
RestrictionBypass bypass;
try {
- bypass = verifyAndGetBypass(uid, packageName, featureId);
+ bypass = verifyAndGetBypass(uid, packageName, attributionTag);
} catch (SecurityException e) {
Slog.e(TAG, "noteOperation", e);
return AppOpsManager.MODE_ERRORED;
}
synchronized (this) {
- final Ops ops = getOpsLocked(uid, packageName, featureId, bypass, true /* edit */);
+ final Ops ops = getOpsLocked(uid, packageName, attributionTag, bypass,
+ true /* edit */);
if (ops == null) {
scheduleOpNotedIfNeededLocked(code, uid, packageName,
AppOpsManager.MODE_IGNORED);
@@ -2983,17 +2991,17 @@
return AppOpsManager.MODE_ERRORED;
}
final Op op = getOpLocked(ops, code, uid, true);
- final FeatureOp featureOp = op.getOrCreateFeature(op, featureId);
+ final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag);
if (isOpRestrictedLocked(uid, code, packageName, bypass)) {
scheduleOpNotedIfNeededLocked(code, uid, packageName,
AppOpsManager.MODE_IGNORED);
return AppOpsManager.MODE_IGNORED;
}
final UidState uidState = ops.uidState;
- if (featureOp.isRunning()) {
+ if (attributedOp.isRunning()) {
Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName + " code "
+ code + " startTime of in progress event="
- + featureOp.mInProgressEvents.valueAt(0).getStartTime());
+ + attributedOp.mInProgressEvents.valueAt(0).getStartTime());
}
final int switchCode = AppOpsManager.opToSwitch(code);
@@ -3005,7 +3013,7 @@
if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
+ packageName);
- featureOp.rejected(uidState.state, flags);
+ attributedOp.rejected(uidState.state, flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName, uidMode);
return uidMode;
}
@@ -3017,26 +3025,31 @@
if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
+ packageName);
- featureOp.rejected(uidState.state, flags);
+ attributedOp.rejected(uidState.state, flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName, mode);
return mode;
}
}
- if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
- + " package " + packageName + (featureId == null ? "" : "." + featureId));
- featureOp.accessed(proxyUid, proxyPackageName, proxyFeatureId, uidState.state, flags);
+ if (DEBUG) {
+ Slog.d(TAG,
+ "noteOperation: allowing code " + code + " uid " + uid + " package "
+ + packageName + (attributionTag == null ? ""
+ : "." + attributionTag));
+ }
+ attributedOp.accessed(proxyUid, proxyPackageName, proxyAttributionTag, uidState.state,
+ flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName,
AppOpsManager.MODE_ALLOWED);
if (shouldCollectAsyncNotedOp) {
- collectAsyncNotedOp(uid, packageName, code, featureId, message);
+ collectAsyncNotedOp(uid, packageName, code, attributionTag, message);
}
return AppOpsManager.MODE_ALLOWED;
}
}
- // TODO moltmann: Allow watching for feature ops
+ // TODO moltmann: Allow watching for attribution ops
@Override
public void startWatchingActive(int[] ops, IAppOpsActiveCallback callback) {
int watchedUid = -1;
@@ -3134,11 +3147,11 @@
* @param uid The uid the op was noted for
* @param packageName The package the op was noted for
* @param opCode The code of the op noted
- * @param featureId The id of the feature to op was noted for
+ * @param attributionTag attribution tag the op was noted for
* @param message The message for the op noting
*/
private void collectAsyncNotedOp(int uid, @NonNull String packageName, int opCode,
- @Nullable String featureId, @NonNull String message) {
+ @Nullable String attributionTag, @NonNull String message) {
Objects.requireNonNull(message);
int callingUid = Binder.getCallingUid();
@@ -3150,10 +3163,10 @@
RemoteCallbackList<IAppOpsAsyncNotedCallback> callbacks = mAsyncOpWatchers.get(key);
AsyncNotedAppOp asyncNotedOp = new AsyncNotedAppOp(opCode, callingUid,
- featureId, message, System.currentTimeMillis());
+ attributionTag, message, System.currentTimeMillis());
final boolean[] wasNoteForwarded = {false};
- reportRuntimeAppOpAccessMessageAsyncLocked(uid, packageName, opCode, featureId,
+ reportRuntimeAppOpAccessMessageAsyncLocked(uid, packageName, opCode, attributionTag,
message);
if (callbacks != null) {
@@ -3164,7 +3177,7 @@
} catch (RemoteException e) {
Slog.e(TAG,
"Could not forward noteOp of " + opCode + " to " + packageName
- + "/" + uid + "(" + featureId + ")", e);
+ + "/" + uid + "(" + attributionTag + ")", e);
}
});
}
@@ -3266,7 +3279,7 @@
@Override
public int startOperation(IBinder clientId, int code, int uid, String packageName,
- String featureId, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp,
+ String attributionTag, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp,
String message) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
@@ -3277,14 +3290,14 @@
RestrictionBypass bypass;
try {
- bypass = verifyAndGetBypass(uid, packageName, featureId);
+ bypass = verifyAndGetBypass(uid, packageName, attributionTag);
} catch (SecurityException e) {
Slog.e(TAG, "startOperation", e);
return AppOpsManager.MODE_ERRORED;
}
synchronized (this) {
- final Ops ops = getOpsLocked(uid, resolvedPackageName, featureId, bypass,
+ final Ops ops = getOpsLocked(uid, resolvedPackageName, attributionTag, bypass,
true /* edit */);
if (ops == null) {
if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid
@@ -3295,7 +3308,7 @@
if (isOpRestrictedLocked(uid, code, resolvedPackageName, bypass)) {
return AppOpsManager.MODE_IGNORED;
}
- final FeatureOp featureOp = op.getOrCreateFeature(op, featureId);
+ final AttributedOp attributedOp = op.getOrCreateAttribution(op, attributionTag);
final int switchCode = AppOpsManager.opToSwitch(code);
final UidState uidState = ops.uidState;
// If there is a non-default per UID policy (we set UID op mode only if
@@ -3308,7 +3321,7 @@
if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
+ resolvedPackageName);
- featureOp.rejected(uidState.state, AppOpsManager.OP_FLAG_SELF);
+ attributedOp.rejected(uidState.state, AppOpsManager.OP_FLAG_SELF);
return uidMode;
}
} else {
@@ -3320,21 +3333,21 @@
if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
+ resolvedPackageName);
- featureOp.rejected(uidState.state, AppOpsManager.OP_FLAG_SELF);
+ attributedOp.rejected(uidState.state, AppOpsManager.OP_FLAG_SELF);
return mode;
}
}
if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
+ " package " + resolvedPackageName);
try {
- featureOp.started(clientId, uidState.state);
+ attributedOp.started(clientId, uidState.state);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
if (shouldCollectAsyncNotedOp) {
- collectAsyncNotedOp(uid, packageName, code, featureId, message);
+ collectAsyncNotedOp(uid, packageName, code, attributionTag, message);
}
return AppOpsManager.MODE_ALLOWED;
@@ -3342,7 +3355,7 @@
@Override
public void finishOperation(IBinder clientId, int code, int uid, String packageName,
- String featureId) {
+ String attributionTag) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
String resolvedPackageName = resolvePackageName(uid, packageName);
@@ -3352,24 +3365,24 @@
RestrictionBypass bypass;
try {
- bypass = verifyAndGetBypass(uid, packageName, featureId);
+ bypass = verifyAndGetBypass(uid, packageName, attributionTag);
} catch (SecurityException e) {
Slog.e(TAG, "Cannot finishOperation", e);
return;
}
synchronized (this) {
- Op op = getOpLocked(code, uid, resolvedPackageName, featureId, bypass, true);
+ Op op = getOpLocked(code, uid, resolvedPackageName, attributionTag, bypass, true);
if (op == null) {
return;
}
- final FeatureOp featureOp = op.mFeatures.get(featureId);
- if (featureOp == null) {
+ final AttributedOp attributedOp = op.mAttributions.get(attributionTag);
+ if (attributedOp == null) {
return;
}
try {
- featureOp.finished(clientId);
+ attributedOp.finished(clientId);
} catch (IllegalStateException e) {
Slog.e(TAG, "Operation not started: uid=" + uid + " pkg="
+ packageName + " op=" + AppOpsManager.opToName(code), e);
@@ -3639,25 +3652,25 @@
*
* @param uid The uid the package belongs to
* @param packageName The package the might belong to the uid
- * @param featureId The feature in the package or {@code null} if no need to verify
+ * @param attributionTag attribution tag or {@code null} if no need to verify
*
* @return {@code true} iff the package is privileged
*/
private @Nullable RestrictionBypass verifyAndGetBypass(int uid, String packageName,
- @Nullable String featureId) {
+ @Nullable String attributionTag) {
if (uid == Process.ROOT_UID) {
// For backwards compatibility, don't check package name for root UID.
return null;
}
- // Do not check if uid/packageName/featureId is already known
+ // Do not check if uid/packageName/attributionTag is already known
synchronized (this) {
UidState uidState = mUidStates.get(uid);
if (uidState != null && uidState.pkgOps != null) {
Ops ops = uidState.pkgOps.get(packageName);
- if (ops != null && (featureId == null || ops.knownFeatureIds.contains(featureId))
- && ops.bypass != null) {
+ if (ops != null && (attributionTag == null || ops.knownAttributionTags.contains(
+ attributionTag)) && ops.bypass != null) {
return ops.bypass;
}
}
@@ -3669,17 +3682,17 @@
int pkgUid;
AndroidPackage pkg = LocalServices.getService(PackageManagerInternal.class).getPackage(
packageName);
- boolean isFeatureIdValid = false;
+ boolean isAttributionTagValid = false;
if (pkg != null) {
- if (featureId == null) {
- isFeatureIdValid = true;
+ if (attributionTag == null) {
+ isAttributionTagValid = true;
} else {
- if (pkg.getFeatures() != null) {
- int numFeatures = pkg.getFeatures().size();
- for (int i = 0; i < numFeatures; i++) {
- if (pkg.getFeatures().get(i).id.equals(featureId)) {
- isFeatureIdValid = true;
+ if (pkg.getAttributions() != null) {
+ int numAttributions = pkg.getAttributions().size();
+ for (int i = 0; i < numAttributions; i++) {
+ if (pkg.getAttributions().get(i).tag.equals(attributionTag)) {
+ isAttributionTagValid = true;
}
}
}
@@ -3689,8 +3702,8 @@
UserHandle.getUserId(uid), UserHandle.getAppId(pkg.getUid()));
bypass = getBypassforPackage(pkg);
} else {
- // Allow any feature id for resolvable uids
- isFeatureIdValid = true;
+ // Allow any attribution tag for resolvable uids
+ isAttributionTagValid = true;
pkgUid = resolveUid(packageName);
if (pkgUid >= 0) {
@@ -3702,9 +3715,9 @@
+ " but it is really " + pkgUid);
}
- if (!isFeatureIdValid) {
+ if (!isAttributionTagValid) {
// TODO moltmann: Switch from logging to enforcement
- Slog.e(TAG, "featureId " + featureId + " not declared in manifest of "
+ Slog.e(TAG, "attributionTag " + attributionTag + " not declared in manifest of "
+ packageName);
}
} finally {
@@ -3719,13 +3732,13 @@
*
* @param uid The uid the package belongs to
* @param packageName The name of the package
- * @param featureId The feature in the package
+ * @param attributionTag attribution tag
* @param bypass When to bypass certain op restrictions (can be null if edit == false)
* @param edit If an ops does not exist, create the ops?
* @return The ops
*/
- private Ops getOpsLocked(int uid, String packageName, @Nullable String featureId,
+ private Ops getOpsLocked(int uid, String packageName, @Nullable String attributionTag,
@Nullable RestrictionBypass bypass, boolean edit) {
UidState uidState = getUidStateLocked(uid, edit);
if (uidState == null) {
@@ -3753,8 +3766,8 @@
ops.bypass = bypass;
}
- if (featureId != null) {
- ops.knownFeatureIds.add(featureId);
+ if (attributionTag != null) {
+ ops.knownAttributionTags.add(attributionTag);
}
}
@@ -3783,15 +3796,15 @@
* @param code The code of the op
* @param uid The uid the of the package
* @param packageName The package name for which to get the state for
- * @param featureId The feature in the package
+ * @param attributionTag The attribution tag
* @param bypass When to bypass certain op restrictions (can be null if edit == false)
* @param edit Iff {@code true} create the {@link Op} object if not yet created
*
* @return The {@link Op state} of the op
*/
private @Nullable Op getOpLocked(int code, int uid, @NonNull String packageName,
- @Nullable String featureId, @Nullable RestrictionBypass bypass, boolean edit) {
- Ops ops = getOpsLocked(uid, packageName, featureId, bypass, edit);
+ @Nullable String attributionTag, @Nullable RestrictionBypass bypass, boolean edit) {
+ Ops ops = getOpsLocked(uid, packageName, attributionTag, bypass, edit);
if (ops == null) {
return null;
}
@@ -4048,9 +4061,9 @@
uidState.evalForegroundOps(mOpModeWatchers);
}
- private void readFeatureOp(XmlPullParser parser, @NonNull Op parent,
- @Nullable String feature) throws NumberFormatException, IOException {
- final FeatureOp featureOp = parent.getOrCreateFeature(parent, feature);
+ private void readAttributionOp(XmlPullParser parser, @NonNull Op parent,
+ @Nullable String attribution) throws NumberFormatException, IOException {
+ final AttributedOp attributedOp = parent.getOrCreateAttribution(parent, attribution);
final long key = XmlUtils.readLongAttribute(parser, "n");
final int uidState = extractUidStateFromKey(key);
@@ -4061,14 +4074,14 @@
final long accessDuration = XmlUtils.readLongAttribute(parser, "d", -1);
final String proxyPkg = XmlUtils.readStringAttribute(parser, "pp");
final int proxyUid = XmlUtils.readIntAttribute(parser, "pu", Process.INVALID_UID);
- final String proxyFeatureId = XmlUtils.readStringAttribute(parser, "pc");
+ final String proxyAttributionTag = XmlUtils.readStringAttribute(parser, "pc");
if (accessTime > 0) {
- featureOp.accessed(accessTime, accessDuration, proxyUid, proxyPkg, proxyFeatureId,
- uidState, opFlags);
+ attributedOp.accessed(accessTime, accessDuration, proxyUid, proxyPkg,
+ proxyAttributionTag, uidState, opFlags);
}
if (rejectTime > 0) {
- featureOp.rejected(rejectTime, uidState, opFlags);
+ attributedOp.rejected(rejectTime, uidState, opFlags);
}
}
@@ -4094,7 +4107,7 @@
}
String tagName = parser.getName();
if (tagName.equals("st")) {
- readFeatureOp(parser, op, XmlUtils.readStringAttribute(parser, "id"));
+ readAttributionOp(parser, op, XmlUtils.readStringAttribute(parser, "id"));
} else {
Slog.w(TAG, "Unknown element under <op>: "
+ parser.getName());
@@ -4208,11 +4221,11 @@
out.attribute(null, "m", Integer.toString(op.getMode()));
}
- for (String featureId : op.getFeatures().keySet()) {
- final OpFeatureEntry feature = op.getFeatures().get(
- featureId);
+ for (String attributionTag : op.getAttributedOpEntries().keySet()) {
+ final AttributedOpEntry attribution =
+ op.getAttributedOpEntries().get(attributionTag);
- final ArraySet<Long> keys = feature.collectKeys();
+ final ArraySet<Long> keys = attribution.collectKeys();
final int keyCount = keys.size();
for (int k = 0; k < keyCount; k++) {
@@ -4221,14 +4234,14 @@
final int uidState = AppOpsManager.extractUidStateFromKey(key);
final int flags = AppOpsManager.extractFlagsFromKey(key);
- final long accessTime = feature.getLastAccessTime(uidState,
+ final long accessTime = attribution.getLastAccessTime(uidState,
uidState, flags);
- final long rejectTime = feature.getLastRejectTime(uidState,
+ final long rejectTime = attribution.getLastRejectTime(uidState,
uidState, flags);
- final long accessDuration = feature.getLastDuration(uidState,
- uidState, flags);
+ final long accessDuration = attribution.getLastDuration(
+ uidState, uidState, flags);
// Proxy information for rejections is not backed up
- final OpEventProxyInfo proxy = feature.getLastProxyInfo(
+ final OpEventProxyInfo proxy = attribution.getLastProxyInfo(
uidState, uidState, flags);
if (accessTime <= 0 && rejectTime <= 0 && accessDuration <= 0
@@ -4237,17 +4250,17 @@
}
String proxyPkg = null;
- String proxyFeatureId = null;
+ String proxyAttributionTag = null;
int proxyUid = Process.INVALID_UID;
if (proxy != null) {
proxyPkg = proxy.getPackageName();
- proxyFeatureId = proxy.getFeatureId();
+ proxyAttributionTag = proxy.getAttributionTag();
proxyUid = proxy.getUid();
}
out.startTag(null, "st");
- if (featureId != null) {
- out.attribute(null, "id", featureId);
+ if (attributionTag != null) {
+ out.attribute(null, "id", attributionTag);
}
out.attribute(null, "n", Long.toString(key));
if (accessTime > 0) {
@@ -4262,8 +4275,8 @@
if (proxyPkg != null) {
out.attribute(null, "pp", proxyPkg);
}
- if (proxyFeatureId != null) {
- out.attribute(null, "pc", proxyFeatureId);
+ if (proxyAttributionTag != null) {
+ out.attribute(null, "pc", proxyAttributionTag);
}
if (proxyUid >= 0) {
out.attribute(null, "pu", Integer.toString(proxyUid));
@@ -4297,7 +4310,7 @@
int userId = UserHandle.USER_SYSTEM;
String packageName;
- String featureId;
+ String attributionTag;
String opStr;
String modeStr;
int op;
@@ -4399,8 +4412,8 @@
userId = UserHandle.parseUserArg(getNextArgRequired());
} else if ("--uid".equals(argument)) {
targetsUid = true;
- } else if ("--feature".equals(argument)) {
- featureId = getNextArgRequired();
+ } else if ("--attribution".equals(argument)) {
+ attributionTag = getNextArgRequired();
} else {
if (packageName == null) {
packageName = argument;
@@ -4495,13 +4508,16 @@
pw.println("AppOps service (appops) commands:");
pw.println(" help");
pw.println(" Print this help text.");
- pw.println(" start [--user <USER_ID>] [--feature <FEATURE_ID>] <PACKAGE | UID> <OP> ");
+ pw.println(" start [--user <USER_ID>] [--attribution <ATTRIBUTION_TAG>] <PACKAGE | UID> "
+ + "<OP> ");
pw.println(" Starts a given operation for a particular application.");
- pw.println(" stop [--user <USER_ID>] [--feature <FEATURE_ID>] <PACKAGE | UID> <OP> ");
+ pw.println(" stop [--user <USER_ID>] [--attribution <ATTRIBUTION_TAG>] <PACKAGE | UID> "
+ + "<OP> ");
pw.println(" Stops a given operation for a particular application.");
pw.println(" set [--user <USER_ID>] <[--uid] PACKAGE | UID> <OP> <MODE>");
pw.println(" Set the mode for a particular application and operation.");
- pw.println(" get [--user <USER_ID>] [--feature <FEATURE_ID>] <PACKAGE | UID> [<OP>]");
+ pw.println(" get [--user <USER_ID>] [--attribution <ATTRIBUTION_TAG>] <PACKAGE | UID> "
+ + "[<OP>]");
pw.println(" Return the mode for a particular application and optional operation.");
pw.println(" query-op [--user <USER_ID>] <OP> [<MODE>]");
pw.println(" Print all packages that currently have the given op in the given mode.");
@@ -4515,8 +4531,8 @@
pw.println(" <PACKAGE> an Android package name or its UID if prefixed by --uid");
pw.println(" <OP> an AppOps operation.");
pw.println(" <MODE> one of allow, ignore, deny, or default");
- pw.println(" <USER_ID> the user id under which the package is installed. If --user is not");
- pw.println(" specified, the current user is assumed.");
+ pw.println(" <USER_ID> the user id under which the package is installed. If --user is");
+ pw.println(" not specified, the current user is assumed.");
}
static int onShellCommand(Shell shell, String cmd) {
@@ -4605,7 +4621,7 @@
pw.print(AppOpsManager.opToName(ent.getOp()));
pw.print(": ");
pw.print(AppOpsManager.modeToName(ent.getMode()));
- if (shell.featureId == null) {
+ if (shell.attributionTag == null) {
if (ent.getLastAccessTime(OP_FLAGS_ALL) != -1) {
pw.print("; time=");
TimeUtils.formatDuration(
@@ -4625,29 +4641,30 @@
TimeUtils.formatDuration(ent.getLastDuration(OP_FLAGS_ALL), pw);
}
} else {
- final OpFeatureEntry featureEnt = ent.getFeatures().get(
- shell.featureId);
- if (featureEnt != null) {
- if (featureEnt.getLastAccessTime(OP_FLAGS_ALL) != -1) {
+ final AppOpsManager.AttributedOpEntry attributionEnt =
+ ent.getAttributedOpEntries().get(shell.attributionTag);
+ if (attributionEnt != null) {
+ if (attributionEnt.getLastAccessTime(OP_FLAGS_ALL) != -1) {
pw.print("; time=");
- TimeUtils.formatDuration(now - featureEnt.getLastAccessTime(
- OP_FLAGS_ALL), pw);
+ TimeUtils.formatDuration(
+ now - attributionEnt.getLastAccessTime(
+ OP_FLAGS_ALL), pw);
pw.print(" ago");
}
- if (featureEnt.getLastRejectTime(OP_FLAGS_ALL) != -1) {
+ if (attributionEnt.getLastRejectTime(OP_FLAGS_ALL) != -1) {
pw.print("; rejectTime=");
TimeUtils.formatDuration(
- now - featureEnt.getLastRejectTime(OP_FLAGS_ALL),
- pw);
+ now - attributionEnt.getLastRejectTime(
+ OP_FLAGS_ALL), pw);
pw.print(" ago");
}
- if (featureEnt.isRunning()) {
+ if (attributionEnt.isRunning()) {
pw.print(" (running)");
- } else if (featureEnt.getLastDuration(OP_FLAGS_ALL)
+ } else if (attributionEnt.getLastDuration(OP_FLAGS_ALL)
!= -1) {
pw.print("; duration=");
TimeUtils.formatDuration(
- featureEnt.getLastDuration(OP_FLAGS_ALL), pw);
+ attributionEnt.getLastDuration(OP_FLAGS_ALL), pw);
}
}
}
@@ -4755,7 +4772,7 @@
if (shell.packageName != null) {
shell.mInterface.startOperation(shell.mToken, shell.op, shell.packageUid,
- shell.packageName, shell.featureId, true, true,
+ shell.packageName, shell.attributionTag, true, true,
"appops start shell command");
} else {
return -1;
@@ -4769,8 +4786,8 @@
}
if (shell.packageName != null) {
- shell.mInterface.finishOperation(shell.mToken,
- shell.op, shell.packageUid, shell.packageName, shell.featureId);
+ shell.mInterface.finishOperation(shell.mToken, shell.op, shell.packageUid,
+ shell.packageName, shell.attributionTag);
} else {
return -1;
}
@@ -4795,35 +4812,35 @@
pw.println(" Limit output to data associated with the given app op mode.");
pw.println(" --package [PACKAGE]");
pw.println(" Limit output to data associated with the given package name.");
- pw.println(" --featureId [featureId]");
- pw.println(" Limit output to data associated with the given feature id.");
+ pw.println(" --attributionTag [attributionTag]");
+ pw.println(" Limit output to data associated with the given attribution tag.");
pw.println(" --watchers");
pw.println(" Only output the watcher sections.");
}
- private void dumpStatesLocked(@NonNull PrintWriter pw, @Nullable String filterFeatureId,
+ private void dumpStatesLocked(@NonNull PrintWriter pw, @Nullable String filterAttributionTag,
@HistoricalOpsRequestFilter int filter, long nowElapsed, @NonNull Op op, long now,
@NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix) {
- final int numFeatures = op.mFeatures.size();
- for (int i = 0; i < numFeatures; i++) {
- if ((filter & FILTER_BY_FEATURE_ID) != 0 && !Objects.equals(op.mFeatures.keyAt(i),
- filterFeatureId)) {
+ final int numAttributions = op.mAttributions.size();
+ for (int i = 0; i < numAttributions; i++) {
+ if ((filter & FILTER_BY_ATTRIBUTION_TAG) != 0 && !Objects.equals(
+ op.mAttributions.keyAt(i), filterAttributionTag)) {
continue;
}
- pw.print(prefix + op.mFeatures.keyAt(i) + "=[\n");
- dumpStatesLocked(pw, nowElapsed, op, op.mFeatures.keyAt(i), now, sdf, date,
+ pw.print(prefix + op.mAttributions.keyAt(i) + "=[\n");
+ dumpStatesLocked(pw, nowElapsed, op, op.mAttributions.keyAt(i), now, sdf, date,
prefix + " ");
pw.print(prefix + "]\n");
}
}
private void dumpStatesLocked(@NonNull PrintWriter pw, long nowElapsed, @NonNull Op op,
- @Nullable String featureId, long now, @NonNull SimpleDateFormat sdf,
+ @Nullable String attributionTag, long now, @NonNull SimpleDateFormat sdf,
@NonNull Date date, @NonNull String prefix) {
- final OpFeatureEntry entry = op.createSingleFeatureEntryLocked(
- featureId).getFeatures().get(featureId);
+ final AttributedOpEntry entry = op.createSingleAttributionEntryLocked(
+ attributionTag).getAttributedOpEntries().get(attributionTag);
final ArraySet<Long> keys = entry.collectKeys();
@@ -4840,11 +4857,11 @@
final OpEventProxyInfo proxy = entry.getLastProxyInfo(uidState, uidState, flags);
String proxyPkg = null;
- String proxyFeatureId = null;
+ String proxyAttributionTag = null;
int proxyUid = Process.INVALID_UID;
if (proxy != null) {
proxyPkg = proxy.getPackageName();
- proxyFeatureId = proxy.getFeatureId();
+ proxyAttributionTag = proxy.getAttributionTag();
proxyUid = proxy.getUid();
}
@@ -4868,8 +4885,8 @@
pw.print(proxyUid);
pw.print(", pkg=");
pw.print(proxyPkg);
- pw.print(", feature=");
- pw.print(proxyFeatureId);
+ pw.print(", attributionTag=");
+ pw.print(proxyAttributionTag);
pw.print("]");
}
pw.println();
@@ -4890,21 +4907,21 @@
pw.print(proxyUid);
pw.print(", pkg=");
pw.print(proxyPkg);
- pw.print(", feature=");
- pw.print(proxyFeatureId);
+ pw.print(", attributionTag=");
+ pw.print(proxyAttributionTag);
pw.print("]");
}
pw.println();
}
}
- final FeatureOp featureOp = op.mFeatures.get(featureId);
- if (featureOp.isRunning()) {
+ final AttributedOp attributedOp = op.mAttributions.get(attributionTag);
+ if (attributedOp.isRunning()) {
long earliestElapsedTime = Long.MAX_VALUE;
long maxNumStarts = 0;
- int numInProgressEvents = featureOp.mInProgressEvents.size();
+ int numInProgressEvents = attributedOp.mInProgressEvents.size();
for (int i = 0; i < numInProgressEvents; i++) {
- InProgressStartOpEvent event = featureOp.mInProgressEvents.valueAt(i);
+ InProgressStartOpEvent event = attributedOp.mInProgressEvents.valueAt(i);
earliestElapsedTime = Math.min(earliestElapsedTime, event.getStartElapsedTime());
maxNumStarts = Math.max(maxNumStarts, event.numUnfinishedStarts);
@@ -4927,7 +4944,7 @@
int dumpOp = OP_NONE;
String dumpPackage = null;
- String dumpFeatureId = null;
+ String dumpAttributionTag = null;
int dumpUid = Process.INVALID_UID;
int dumpMode = -1;
boolean dumpWatchers = false;
@@ -4974,14 +4991,14 @@
}
dumpUid = UserHandle.getAppId(dumpUid);
dumpFilter |= FILTER_BY_UID;
- } else if ("--featureId".equals(arg)) {
+ } else if ("--attributionTag".equals(arg)) {
i++;
if (i >= args.length) {
- pw.println("No argument for --featureId option");
+ pw.println("No argument for --attributionTag option");
return;
}
- dumpFeatureId = args[i];
- dumpFilter |= FILTER_BY_FEATURE_ID;
+ dumpAttributionTag = args[i];
+ dumpFilter |= FILTER_BY_ATTRIBUTION_TAG;
} else if ("--mode".equals(arg)) {
i++;
if (i >= args.length) {
@@ -5320,8 +5337,8 @@
pw.print("="); pw.print(AppOpsManager.modeToName(mode));
}
pw.println("): ");
- dumpStatesLocked(pw, dumpFeatureId, dumpFilter, nowElapsed, op, now, sdf,
- date, " ");
+ dumpStatesLocked(pw, dumpAttributionTag, dumpFilter, nowElapsed, op, now,
+ sdf, date, " ");
}
}
}
@@ -5420,7 +5437,7 @@
// Must not hold the appops lock
if (dumpHistory && !dumpWatchers) {
- mHistoricalRegistry.dump(" ", pw, dumpUid, dumpPackage, dumpFeatureId, dumpOp,
+ mHistoricalRegistry.dump(" ", pw, dumpUid, dumpPackage, dumpAttributionTag, dumpOp,
dumpFilter);
}
}
@@ -5525,7 +5542,7 @@
if (resolvedPackageName == null) {
return false;
}
- // TODO moltmann: Allow to check for feature op activeness
+ // TODO moltmann: Allow to check for attribution op activeness
synchronized (AppOpsService.this) {
Ops pkgOps = getOpsLocked(uid, resolvedPackageName, null, null, false);
if (pkgOps == null) {
@@ -5586,7 +5603,7 @@
* Report runtime access to AppOp together with message (including stack trace)
*
* @param packageName The package which reported the op
- * @param notedAppOp contains code of op and featureId provided by developer
+ * @param notedAppOp contains code of op and attributionTag provided by developer
* @param message Message describing AppOp access (can be stack trace)
*
* @return Config for future sampling to reduce amount of reporting
@@ -5608,7 +5625,7 @@
reportRuntimeAppOpAccessMessageInternalLocked(uid, packageName,
AppOpsManager.strOpToOp(notedAppOp.getOp()),
- notedAppOp.getFeatureId(), message);
+ notedAppOp.getAttributionTag(), message);
return new MessageSamplingConfig(mSampledAppOpCode, mAcceptableLeftDistance,
Instant.now().plus(1, ChronoUnit.HOURS).toEpochMilli());
@@ -5621,17 +5638,18 @@
* @param uid Uid of the package which reported the op
* @param packageName The package which reported the op
* @param opCode Code of AppOp
- * @param featureId FeautreId of AppOp reported
+ * @param attributionTag FeautreId of AppOp reported
* @param message Message describing AppOp access (can be stack trace)
*/
private void reportRuntimeAppOpAccessMessageAsyncLocked(int uid,
- @NonNull String packageName, int opCode, @Nullable String featureId,
+ @NonNull String packageName, int opCode, @Nullable String attributionTag,
@NonNull String message) {
switchPackageIfRarelyUsedLocked(packageName);
if (!Objects.equals(mSampledPackage, packageName)) {
return;
}
- reportRuntimeAppOpAccessMessageInternalLocked(uid, packageName, opCode, featureId, message);
+ reportRuntimeAppOpAccessMessageInternalLocked(uid, packageName, opCode, attributionTag,
+ message);
}
/**
@@ -5639,7 +5657,7 @@
* reporting uniformly at random across all received messages.
*/
private void reportRuntimeAppOpAccessMessageInternalLocked(int uid,
- @NonNull String packageName, int opCode, @Nullable String featureId,
+ @NonNull String packageName, int opCode, @Nullable String attributionTag,
@NonNull String message) {
int newLeftDistance = AppOpsManager.leftCircularDistance(opCode,
mSampledAppOpCode, _NUM_OP);
@@ -5656,7 +5674,7 @@
mMessagesCollectedCount += 1.0f;
if (ThreadLocalRandom.current().nextFloat() <= 1.0f / mMessagesCollectedCount) {
mCollectedRuntimePermissionMessage = new RuntimeAppOpAccessMessage(uid, opCode,
- packageName, featureId, message, mSamplingStrategy);
+ packageName, attributionTag, message, mSamplingStrategy);
}
return;
}
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index cd450d4..ed45069 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -15,7 +15,7 @@
*/
package com.android.server.appop;
-import static android.app.AppOpsManager.FILTER_BY_FEATURE_ID;
+import static android.app.AppOpsManager.FILTER_BY_ATTRIBUTION_TAG;
import static android.app.AppOpsManager.FILTER_BY_OP_NAMES;
import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME;
import static android.app.AppOpsManager.FILTER_BY_UID;
@@ -23,7 +23,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
-import android.app.AppOpsManager.HistoricalFeatureOps;
import android.app.AppOpsManager.HistoricalMode;
import android.app.AppOpsManager.HistoricalOp;
import android.app.AppOpsManager.HistoricalOps;
@@ -282,7 +281,7 @@
}
void dump(String prefix, PrintWriter pw, int filterUid, @Nullable String filterPackage,
- @Nullable String filterFeatureId, int filterOp,
+ @Nullable String filterAttributionTag, int filterOp,
@HistoricalOpsRequestFilter int filter) {
if (!isApiEnabled()) {
return;
@@ -298,7 +297,7 @@
pw.println(AppOpsManager.historicalModeToString(mMode));
final StringDumpVisitor visitor = new StringDumpVisitor(prefix + " ",
- pw, filterUid, filterPackage, filterFeatureId, filterOp, filter);
+ pw, filterUid, filterPackage, filterAttributionTag, filterOp, filter);
final long nowMillis = System.currentTimeMillis();
// Dump in memory state first
@@ -338,7 +337,7 @@
}
void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName,
- @Nullable String featureId, @Nullable String[] opNames,
+ @Nullable String attributionTag, @Nullable String[] opNames,
@HistoricalOpsRequestFilter int filter, long beginTimeMillis, long endTimeMillis,
@OpFlags int flags, @NonNull RemoteCallback callback) {
if (!isApiEnabled()) {
@@ -354,7 +353,7 @@
return;
}
final HistoricalOps result = new HistoricalOps(beginTimeMillis, endTimeMillis);
- mPersistence.collectHistoricalOpsDLocked(result, uid, packageName, featureId,
+ mPersistence.collectHistoricalOpsDLocked(result, uid, packageName, attributionTag,
opNames, filter, beginTimeMillis, endTimeMillis, flags);
final Bundle payload = new Bundle();
payload.putParcelable(AppOpsManager.KEY_HISTORICAL_OPS, result);
@@ -363,7 +362,7 @@
}
}
- void getHistoricalOps(int uid, @NonNull String packageName, @Nullable String featureId,
+ void getHistoricalOps(int uid, @NonNull String packageName, @Nullable String attributionTag,
@Nullable String[] opNames, @HistoricalOpsRequestFilter int filter,
long beginTimeMillis, long endTimeMillis, @OpFlags int flags,
@NonNull RemoteCallback callback) {
@@ -401,7 +400,7 @@
|| inMemoryAdjEndTimeMillis <= currentOps.getBeginTimeMillis())) {
// Some of the current batch falls into the query, so extract that.
final HistoricalOps currentOpsCopy = new HistoricalOps(currentOps);
- currentOpsCopy.filter(uid, packageName, featureId, opNames, filter,
+ currentOpsCopy.filter(uid, packageName, attributionTag, opNames, filter,
inMemoryAdjBeginTimeMillis, inMemoryAdjEndTimeMillis);
result.merge(currentOpsCopy);
}
@@ -421,7 +420,7 @@
- onDiskAndInMemoryOffsetMillis, 0);
final long onDiskAdjEndTimeMillis = Math.max(inMemoryAdjEndTimeMillis
- onDiskAndInMemoryOffsetMillis, 0);
- mPersistence.collectHistoricalOpsDLocked(result, uid, packageName, featureId,
+ mPersistence.collectHistoricalOpsDLocked(result, uid, packageName, attributionTag,
opNames, filter, onDiskAdjBeginTimeMillis, onDiskAdjEndTimeMillis, flags);
}
@@ -436,7 +435,7 @@
}
void incrementOpAccessedCount(int op, int uid, @NonNull String packageName,
- @Nullable String featureId, @UidState int uidState, @OpFlags int flags) {
+ @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags) {
synchronized (mInMemoryLock) {
if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
if (!isPersistenceInitializedMLocked()) {
@@ -445,13 +444,13 @@
}
getUpdatedPendingHistoricalOpsMLocked(
System.currentTimeMillis()).increaseAccessCount(op, uid, packageName,
- featureId, uidState, flags, 1);
+ attributionTag, uidState, flags, 1);
}
}
}
void incrementOpRejected(int op, int uid, @NonNull String packageName,
- @Nullable String featureId, @UidState int uidState, @OpFlags int flags) {
+ @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags) {
synchronized (mInMemoryLock) {
if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
if (!isPersistenceInitializedMLocked()) {
@@ -460,13 +459,13 @@
}
getUpdatedPendingHistoricalOpsMLocked(
System.currentTimeMillis()).increaseRejectCount(op, uid, packageName,
- featureId, uidState, flags, 1);
+ attributionTag, uidState, flags, 1);
}
}
}
void increaseOpAccessDuration(int op, int uid, @NonNull String packageName,
- @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ @Nullable String attributionTag, @UidState int uidState, @OpFlags int flags,
long increment) {
synchronized (mInMemoryLock) {
if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
@@ -476,7 +475,7 @@
}
getUpdatedPendingHistoricalOpsMLocked(
System.currentTimeMillis()).increaseAccessDuration(op, uid, packageName,
- featureId, uidState, flags, increment);
+ attributionTag, uidState, flags, increment);
}
}
}
@@ -728,7 +727,7 @@
private static final String TAG_OPS = "ops";
private static final String TAG_UID = "uid";
private static final String TAG_PACKAGE = "pkg";
- private static final String TAG_FEATURE = "ftr";
+ private static final String TAG_ATTRIBUTION = "ftr";
private static final String TAG_OP = "op";
private static final String TAG_STATE = "st";
@@ -807,9 +806,9 @@
@Nullable List<HistoricalOps> readHistoryRawDLocked() {
return collectHistoricalOpsBaseDLocked(Process.INVALID_UID /*filterUid*/,
- null /*filterPackageName*/, null /*filterFeatureId*/, null /*filterOpNames*/,
- 0 /*filter*/, 0 /*filterBeginTimeMills*/, Long.MAX_VALUE /*filterEndTimeMills*/,
- AppOpsManager.OP_FLAGS_ALL);
+ null /*filterPackageName*/, null /*filterAttributionTag*/,
+ null /*filterOpNames*/, 0 /*filter*/, 0 /*filterBeginTimeMills*/,
+ Long.MAX_VALUE /*filterEndTimeMills*/, AppOpsManager.OP_FLAGS_ALL);
}
@Nullable List<HistoricalOps> readHistoryDLocked() {
@@ -861,13 +860,13 @@
return 0;
}
- private void collectHistoricalOpsDLocked(@NonNull HistoricalOps currentOps,
- int filterUid, @Nullable String filterPackageName, @Nullable String filterFeatureId,
+ private void collectHistoricalOpsDLocked(@NonNull HistoricalOps currentOps, int filterUid,
+ @Nullable String filterPackageName, @Nullable String filterAttributionTag,
@Nullable String[] filterOpNames, @HistoricalOpsRequestFilter int filter,
long filterBeingMillis, long filterEndMillis, @OpFlags int filterFlags) {
final List<HistoricalOps> readOps = collectHistoricalOpsBaseDLocked(filterUid,
- filterPackageName, filterFeatureId, filterOpNames, filter, filterBeingMillis,
- filterEndMillis, filterFlags);
+ filterPackageName, filterAttributionTag, filterOpNames, filter,
+ filterBeingMillis, filterEndMillis, filterFlags);
if (readOps != null) {
final int readCount = readOps.size();
for (int i = 0; i < readCount; i++) {
@@ -877,8 +876,8 @@
}
}
- private @Nullable LinkedList<HistoricalOps> collectHistoricalOpsBaseDLocked(
- int filterUid, @Nullable String filterPackageName, @Nullable String filterFeatureId,
+ private @Nullable LinkedList<HistoricalOps> collectHistoricalOpsBaseDLocked(int filterUid,
+ @Nullable String filterPackageName, @Nullable String filterAttributionTag,
@Nullable String[] filterOpNames, @HistoricalOpsRequestFilter int filter,
long filterBeginTimeMillis, long filterEndTimeMillis, @OpFlags int filterFlags) {
File baseDir = null;
@@ -892,7 +891,7 @@
final Set<String> historyFiles = getHistoricalFileNames(baseDir);
final long[] globalContentOffsetMillis = {0};
final LinkedList<HistoricalOps> ops = collectHistoricalOpsRecursiveDLocked(
- baseDir, filterUid, filterPackageName, filterFeatureId, filterOpNames,
+ baseDir, filterUid, filterPackageName, filterAttributionTag, filterOpNames,
filter, filterBeginTimeMillis, filterEndTimeMillis, filterFlags,
globalContentOffsetMillis, null /*outOps*/, 0 /*depth*/, historyFiles);
if (DEBUG) {
@@ -909,7 +908,7 @@
private @Nullable LinkedList<HistoricalOps> collectHistoricalOpsRecursiveDLocked(
@NonNull File baseDir, int filterUid, @Nullable String filterPackageName,
- @Nullable String filterFeatureId, @Nullable String[] filterOpNames,
+ @Nullable String filterAttributionTag, @Nullable String[] filterOpNames,
@HistoricalOpsRequestFilter int filter, long filterBeginTimeMillis,
long filterEndTimeMillis, @OpFlags int filterFlags,
@NonNull long[] globalContentOffsetMillis,
@@ -927,7 +926,7 @@
// Read historical data at this level
final List<HistoricalOps> readOps = readHistoricalOpsLocked(baseDir,
previousIntervalEndMillis, currentIntervalEndMillis, filterUid,
- filterPackageName, filterFeatureId, filterOpNames, filter,
+ filterPackageName, filterAttributionTag, filterOpNames, filter,
filterBeginTimeMillis, filterEndTimeMillis, filterFlags,
globalContentOffsetMillis, depth, historyFiles);
// Empty is a special signal to stop diving
@@ -937,7 +936,7 @@
// Collect older historical data from subsequent levels
outOps = collectHistoricalOpsRecursiveDLocked(baseDir, filterUid, filterPackageName,
- filterFeatureId, filterOpNames, filter, filterBeginTimeMillis,
+ filterAttributionTag, filterOpNames, filter, filterBeginTimeMillis,
filterEndTimeMillis, filterFlags, globalContentOffsetMillis, outOps, depth + 1,
historyFiles);
@@ -1006,7 +1005,7 @@
final List<HistoricalOps> existingOps = readHistoricalOpsLocked(oldBaseDir,
previousIntervalEndMillis, currentIntervalEndMillis,
Process.INVALID_UID /*filterUid*/, null /*filterPackageName*/,
- null /*filterFeatureId*/, null /*filterOpNames*/, 0 /*filter*/,
+ null /*filterAttributionTag*/, null /*filterOpNames*/, 0 /*filter*/,
Long.MIN_VALUE /*filterBeginTimeMillis*/,
Long.MAX_VALUE /*filterEndTimeMillis*/, AppOpsManager.OP_FLAGS_ALL, null, depth,
null /*historyFiles*/);
@@ -1120,7 +1119,7 @@
private @Nullable List<HistoricalOps> readHistoricalOpsLocked(File baseDir,
long intervalBeginMillis, long intervalEndMillis, int filterUid,
- @Nullable String filterPackageName, @Nullable String filterFeatureId,
+ @Nullable String filterPackageName, @Nullable String filterAttributionTag,
@Nullable String[] filterOpNames, @HistoricalOpsRequestFilter int filter,
long filterBeginTimeMillis, long filterEndTimeMillis, @OpFlags int filterFlags,
@Nullable long[] cumulativeOverflowMillis, int depth,
@@ -1147,15 +1146,16 @@
return null;
}
}
- return readHistoricalOpsLocked(file, filterUid, filterPackageName, filterFeatureId,
+ return readHistoricalOpsLocked(file, filterUid, filterPackageName, filterAttributionTag,
filterOpNames, filter, filterBeginTimeMillis, filterEndTimeMillis, filterFlags,
cumulativeOverflowMillis);
}
- private @Nullable List<HistoricalOps> readHistoricalOpsLocked(@NonNull File file,
- int filterUid, @Nullable String filterPackageName, @Nullable String filterFeatureId,
- @Nullable String[] filterOpNames, @HistoricalOpsRequestFilter int filter,
- long filterBeginTimeMillis, long filterEndTimeMillis, @OpFlags int filterFlags,
+ private @Nullable List<HistoricalOps> readHistoricalOpsLocked(@NonNull File file,
+ int filterUid, @Nullable String filterPackageName,
+ @Nullable String filterAttributionTag, @Nullable String[] filterOpNames,
+ @HistoricalOpsRequestFilter int filter, long filterBeginTimeMillis,
+ long filterEndTimeMillis, @OpFlags int filterFlags,
@Nullable long[] cumulativeOverflowMillis)
throws IOException, XmlPullParserException {
if (DEBUG) {
@@ -1180,7 +1180,7 @@
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_OPS.equals(parser.getName())) {
final HistoricalOps ops = readeHistoricalOpsDLocked(parser, filterUid,
- filterPackageName, filterFeatureId, filterOpNames, filter,
+ filterPackageName, filterAttributionTag, filterOpNames, filter,
filterBeginTimeMillis, filterEndTimeMillis, filterFlags,
cumulativeOverflowMillis);
if (ops == null) {
@@ -1215,7 +1215,7 @@
private @Nullable HistoricalOps readeHistoricalOpsDLocked(
@NonNull XmlPullParser parser, int filterUid, @Nullable String filterPackageName,
- @Nullable String filterFeatureId, @Nullable String[] filterOpNames,
+ @Nullable String filterAttributionTag, @Nullable String[] filterOpNames,
@HistoricalOpsRequestFilter int filter, long filterBeginTimeMillis,
long filterEndTimeMillis, @OpFlags int filterFlags,
@Nullable long[] cumulativeOverflowMillis)
@@ -1245,8 +1245,8 @@
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_UID.equals(parser.getName())) {
final HistoricalOps returnedOps = readHistoricalUidOpsDLocked(ops, parser,
- filterUid, filterPackageName, filterFeatureId, filterOpNames, filter,
- filterFlags, filterScale);
+ filterUid, filterPackageName, filterAttributionTag, filterOpNames,
+ filter, filterFlags, filterScale);
if (ops == null) {
ops = returnedOps;
}
@@ -1260,7 +1260,7 @@
private @Nullable HistoricalOps readHistoricalUidOpsDLocked(
@Nullable HistoricalOps ops, @NonNull XmlPullParser parser, int filterUid,
- @Nullable String filterPackageName, @Nullable String filterFeatureId,
+ @Nullable String filterPackageName, @Nullable String filterAttributionTag,
@Nullable String[] filterOpNames, @HistoricalOpsRequestFilter int filter,
@OpFlags int filterFlags, double filterScale)
throws IOException, XmlPullParserException {
@@ -1272,8 +1272,8 @@
final int depth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_PACKAGE.equals(parser.getName())) {
- final HistoricalOps returnedOps = readHistoricalPackageOpsDLocked(ops,
- uid, parser, filterPackageName, filterFeatureId, filterOpNames, filter,
+ final HistoricalOps returnedOps = readHistoricalPackageOpsDLocked(ops, uid,
+ parser, filterPackageName, filterAttributionTag, filterOpNames, filter,
filterFlags, filterScale);
if (ops == null) {
ops = returnedOps;
@@ -1285,7 +1285,7 @@
private @Nullable HistoricalOps readHistoricalPackageOpsDLocked(
@Nullable HistoricalOps ops, int uid, @NonNull XmlPullParser parser,
- @Nullable String filterPackageName, @Nullable String filterFeatureId,
+ @Nullable String filterPackageName, @Nullable String filterAttributionTag,
@Nullable String[] filterOpNames, @HistoricalOpsRequestFilter int filter,
@OpFlags int filterFlags, double filterScale)
throws IOException, XmlPullParserException {
@@ -1296,9 +1296,9 @@
}
final int depth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, depth)) {
- if (TAG_FEATURE.equals(parser.getName())) {
- final HistoricalOps returnedOps = readHistoricalFeatureOpsDLocked(ops, uid,
- packageName, parser, filterFeatureId, filterOpNames, filter,
+ if (TAG_ATTRIBUTION.equals(parser.getName())) {
+ final HistoricalOps returnedOps = readHistoricalAttributionOpsDLocked(ops, uid,
+ packageName, parser, filterAttributionTag, filterOpNames, filter,
filterFlags, filterScale);
if (ops == null) {
ops = returnedOps;
@@ -1308,15 +1308,15 @@
return ops;
}
- private @Nullable HistoricalOps readHistoricalFeatureOpsDLocked(@Nullable HistoricalOps ops,
- int uid, String packageName, @NonNull XmlPullParser parser,
- @Nullable String filterFeatureId, @Nullable String[] filterOpNames,
- @HistoricalOpsRequestFilter int filter, @OpFlags int filterFlags,
- double filterScale)
+ private @Nullable HistoricalOps readHistoricalAttributionOpsDLocked(
+ @Nullable HistoricalOps ops, int uid, String packageName,
+ @NonNull XmlPullParser parser, @Nullable String filterAttributionTag,
+ @Nullable String[] filterOpNames, @HistoricalOpsRequestFilter int filter,
+ @OpFlags int filterFlags, double filterScale)
throws IOException, XmlPullParserException {
- final String featureId = XmlUtils.readStringAttribute(parser, ATTR_NAME);
- if ((filter & FILTER_BY_FEATURE_ID) != 0 && !Objects.equals(filterFeatureId,
- featureId)) {
+ final String attributionTag = XmlUtils.readStringAttribute(parser, ATTR_NAME);
+ if ((filter & FILTER_BY_ATTRIBUTION_TAG) != 0 && !Objects.equals(filterAttributionTag,
+ attributionTag)) {
XmlUtils.skipCurrentTag(parser);
return null;
}
@@ -1324,7 +1324,8 @@
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_OP.equals(parser.getName())) {
final HistoricalOps returnedOps = readHistoricalOpDLocked(ops, uid, packageName,
- featureId, parser, filterOpNames, filter, filterFlags, filterScale);
+ attributionTag, parser, filterOpNames, filter, filterFlags,
+ filterScale);
if (ops == null) {
ops = returnedOps;
}
@@ -1334,7 +1335,7 @@
}
private @Nullable HistoricalOps readHistoricalOpDLocked(@Nullable HistoricalOps ops,
- int uid, @NonNull String packageName, @Nullable String featureId,
+ int uid, @NonNull String packageName, @Nullable String attributionTag,
@NonNull XmlPullParser parser, @Nullable String[] filterOpNames,
@HistoricalOpsRequestFilter int filter, @OpFlags int filterFlags,
double filterScale)
@@ -1349,7 +1350,7 @@
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_STATE.equals(parser.getName())) {
final HistoricalOps returnedOps = readStateDLocked(ops, uid,
- packageName, featureId, op, parser, filterFlags, filterScale);
+ packageName, attributionTag, op, parser, filterFlags, filterScale);
if (ops == null) {
ops = returnedOps;
}
@@ -1359,7 +1360,7 @@
}
private @Nullable HistoricalOps readStateDLocked(@Nullable HistoricalOps ops,
- int uid, @NonNull String packageName, @Nullable String featureId, int op,
+ int uid, @NonNull String packageName, @Nullable String attributionTag, int op,
@NonNull XmlPullParser parser, @OpFlags int filterFlags, double filterScale)
throws IOException {
final long key = XmlUtils.readLongAttribute(parser, ATTR_NAME);
@@ -1377,7 +1378,7 @@
if (ops == null) {
ops = new HistoricalOps(0, 0);
}
- ops.increaseAccessCount(op, uid, packageName, featureId, uidState, flags,
+ ops.increaseAccessCount(op, uid, packageName, attributionTag, uidState, flags,
accessCount);
}
long rejectCount = XmlUtils.readLongAttribute(parser, ATTR_REJECT_COUNT, 0);
@@ -1389,7 +1390,7 @@
if (ops == null) {
ops = new HistoricalOps(0, 0);
}
- ops.increaseRejectCount(op, uid, packageName, featureId, uidState, flags,
+ ops.increaseRejectCount(op, uid, packageName, attributionTag, uidState, flags,
rejectCount);
}
long accessDuration = XmlUtils.readLongAttribute(parser, ATTR_ACCESS_DURATION, 0);
@@ -1401,7 +1402,7 @@
if (ops == null) {
ops = new HistoricalOps(0, 0);
}
- ops.increaseAccessDuration(op, uid, packageName, featureId, uidState, flags,
+ ops.increaseAccessDuration(op, uid, packageName, attributionTag, uidState, flags,
accessDuration);
}
return ops;
@@ -1467,24 +1468,25 @@
@NonNull XmlSerializer serializer) throws IOException {
serializer.startTag(null, TAG_PACKAGE);
serializer.attribute(null, ATTR_NAME, packageOps.getPackageName());
- final int numFeatures = packageOps.getFeatureCount();
- for (int i = 0; i < numFeatures; i++) {
- final HistoricalFeatureOps op = packageOps.getFeatureOpsAt(i);
- writeHistoricalFeatureOpsDLocked(op, serializer);
+ final int numAttributions = packageOps.getAttributedOpsCount();
+ for (int i = 0; i < numAttributions; i++) {
+ final AppOpsManager.AttributedHistoricalOps op = packageOps.getAttributedOpsAt(i);
+ writeHistoricalAttributionOpsDLocked(op, serializer);
}
serializer.endTag(null, TAG_PACKAGE);
}
- private void writeHistoricalFeatureOpsDLocked(@NonNull HistoricalFeatureOps featureOps,
+ private void writeHistoricalAttributionOpsDLocked(
+ @NonNull AppOpsManager.AttributedHistoricalOps attributionOps,
@NonNull XmlSerializer serializer) throws IOException {
- serializer.startTag(null, TAG_FEATURE);
- XmlUtils.writeStringAttribute(serializer, ATTR_NAME, featureOps.getFeatureId());
- final int opCount = featureOps.getOpCount();
+ serializer.startTag(null, TAG_ATTRIBUTION);
+ XmlUtils.writeStringAttribute(serializer, ATTR_NAME, attributionOps.getTag());
+ final int opCount = attributionOps.getOpCount();
for (int i = 0; i < opCount; i++) {
- final HistoricalOp op = featureOps.getOpAt(i);
+ final HistoricalOp op = attributionOps.getOpAt(i);
writeHistoricalOpDLocked(op, serializer);
}
- serializer.endTag(null, TAG_FEATURE);
+ serializer.endTag(null, TAG_ATTRIBUTION);
}
private void writeHistoricalOpDLocked(@NonNull HistoricalOp op,
@@ -1718,29 +1720,29 @@
private final @NonNull String mOpsPrefix;
private final @NonNull String mUidPrefix;
private final @NonNull String mPackagePrefix;
- private final @NonNull String mFeaturePrefix;
+ private final @NonNull String mAttributionPrefix;
private final @NonNull String mEntryPrefix;
private final @NonNull String mUidStatePrefix;
private final @NonNull PrintWriter mWriter;
private final int mFilterUid;
private final String mFilterPackage;
- private final String mFilterFeatureId;
+ private final String mFilterAttributionTag;
private final int mFilterOp;
private final @HistoricalOpsRequestFilter int mFilter;
StringDumpVisitor(@NonNull String prefix, @NonNull PrintWriter writer, int filterUid,
- @Nullable String filterPackage, @Nullable String filterFeatureId, int filterOp,
+ @Nullable String filterPackage, @Nullable String filterAttributionTag, int filterOp,
@HistoricalOpsRequestFilter int filter) {
mOpsPrefix = prefix + " ";
mUidPrefix = mOpsPrefix + " ";
mPackagePrefix = mUidPrefix + " ";
- mFeaturePrefix = mPackagePrefix + " ";
- mEntryPrefix = mFeaturePrefix + " ";
+ mAttributionPrefix = mPackagePrefix + " ";
+ mEntryPrefix = mAttributionPrefix + " ";
mUidStatePrefix = mEntryPrefix + " ";
mWriter = writer;
mFilterUid = filterUid;
mFilterPackage = filterPackage;
- mFilterFeatureId = filterFeatureId;
+ mFilterAttributionTag = filterAttributionTag;
mFilterOp = filterOp;
mFilter = filter;
}
@@ -1791,14 +1793,14 @@
}
@Override
- public void visitHistoricalFeatureOps(HistoricalFeatureOps ops) {
- if ((mFilter & FILTER_BY_FEATURE_ID) != 0 && !Objects.equals(mFilterPackage,
- ops.getFeatureId())) {
+ public void visitHistoricalAttributionOps(AppOpsManager.AttributedHistoricalOps ops) {
+ if ((mFilter & FILTER_BY_ATTRIBUTION_TAG) != 0 && !Objects.equals(mFilterPackage,
+ ops.getTag())) {
return;
}
- mWriter.print(mFeaturePrefix);
- mWriter.print("Feature ");
- mWriter.print(ops.getFeatureId());
+ mWriter.print(mAttributionPrefix);
+ mWriter.print("Attribution ");
+ mWriter.print(ops.getTag());
mWriter.println(":");
}
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 61bede9..b2ea311 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -314,6 +314,63 @@
}
}
+ private long[] getAllowedChangesAfterTargetSdkForPackage(String packageName,
+ int targetSdkVersion)
+ throws RemoteException {
+ LongArray allowed = new LongArray();
+ synchronized (mChanges) {
+ for (int i = 0; i < mChanges.size(); ++i) {
+ try {
+ CompatChange change = mChanges.valueAt(i);
+ if (change.getEnableAfterTargetSdk() != targetSdkVersion) {
+ continue;
+ }
+ OverrideAllowedState allowedState =
+ mOverrideValidator.getOverrideAllowedState(change.getId(),
+ packageName);
+ if (allowedState.state == OverrideAllowedState.ALLOWED) {
+ allowed.add(change.getId());
+ }
+ } catch (RemoteException e) {
+ // Should never occur, since validator is in the same process.
+ throw new RuntimeException("Unable to call override validator!", e);
+ }
+ }
+ }
+ return allowed.toArray();
+ }
+
+ /**
+ * Enables all changes with enabledAfterTargetSdk == {@param targetSdkVersion} for
+ * {@param packageName}.
+ *
+ * @return The number of changes that were toggled.
+ */
+ int enableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
+ throws RemoteException {
+ long[] changes = getAllowedChangesAfterTargetSdkForPackage(packageName, targetSdkVersion);
+ for (long changeId : changes) {
+ addOverride(changeId, packageName, true);
+ }
+ return changes.length;
+ }
+
+
+ /**
+ * Disables all changes with enabledAfterTargetSdk == {@param targetSdkVersion} for
+ * {@param packageName}.
+ *
+ * @return The number of changes that were toggled.
+ */
+ int disableTargetSdkChangesForPackage(String packageName, int targetSdkVersion)
+ throws RemoteException {
+ long[] changes = getAllowedChangesAfterTargetSdkForPackage(packageName, targetSdkVersion);
+ for (long changeId : changes) {
+ addOverride(changeId, packageName, false);
+ }
+ return changes.length;
+ }
+
boolean registerListener(long changeId, CompatChange.ChangeListener listener) {
boolean alreadyKnown = true;
synchronized (mChanges) {
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 821653a..8519b00 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -166,6 +166,26 @@
}
@Override
+ public int enableTargetSdkChanges(String packageName, int targetSdkVersion)
+ throws RemoteException, SecurityException {
+ checkCompatChangeOverridePermission();
+ int numChanges = mCompatConfig.enableTargetSdkChangesForPackage(packageName,
+ targetSdkVersion);
+ killPackage(packageName);
+ return numChanges;
+ }
+
+ @Override
+ public int disableTargetSdkChanges(String packageName, int targetSdkVersion)
+ throws RemoteException, SecurityException {
+ checkCompatChangeOverridePermission();
+ int numChanges = mCompatConfig.disableTargetSdkChangesForPackage(packageName,
+ targetSdkVersion);
+ killPackage(packageName);
+ return numChanges;
+ }
+
+ @Override
public void clearOverrides(String packageName) throws RemoteException, SecurityException {
checkCompatChangeOverridePermission();
mCompatConfig.removePackageOverrides(packageName);
diff --git a/services/core/java/com/android/server/location/CountryDetectorBase.java b/services/core/java/com/android/server/location/CountryDetectorBase.java
index b158388..682b104 100644
--- a/services/core/java/com/android/server/location/CountryDetectorBase.java
+++ b/services/core/java/com/android/server/location/CountryDetectorBase.java
@@ -31,7 +31,7 @@
* @hide
*/
public abstract class CountryDetectorBase {
- private static final String FEATURE_ID = "CountryDetector";
+ private static final String ATTRIBUTION_TAG = "CountryDetector";
protected final Handler mHandler;
protected final Context mContext;
@@ -39,7 +39,7 @@
protected Country mDetectedCountry;
public CountryDetectorBase(Context context) {
- mContext = context.createFeatureContext(FEATURE_ID);
+ mContext = context.createAttributionContext(ATTRIBUTION_TAG);
mHandler = new Handler();
}
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index ec9b37d..83da381 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -45,6 +45,7 @@
import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.os.Binder;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -183,7 +184,8 @@
String callingFeatureId,
Intent intent,
@UserIdInt int userId,
- IBinder callingActivity) throws RemoteException {
+ IBinder callingActivity,
+ Bundle options) throws RemoteException {
Objects.requireNonNull(callingPackage);
Objects.requireNonNull(intent);
Objects.requireNonNull(intent.getComponent(), "The intent must have a Component set");
@@ -226,7 +228,7 @@
launchIntent,
callingActivity,
/* startFlags= */ 0,
- /* options= */ null,
+ options,
userId);
logStartActivityByIntent(callingPackage);
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 33ef2d4..cdc3736 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -805,26 +805,30 @@
public SessionInfo getSessionInfo(int sessionId) {
synchronized (mSessions) {
final PackageInstallerSession session = mSessions.get(sessionId);
- return session != null ? session.generateInfo() : null;
+
+ return session != null
+ ? session.generateInfoForCaller(true /*withIcon*/, Binder.getCallingUid())
+ : null;
}
}
@Override
public ParceledListSlice<SessionInfo> getStagedSessions() {
- return mStagingManager.getSessions();
+ return mStagingManager.getSessions(Binder.getCallingUid());
}
@Override
public ParceledListSlice<SessionInfo> getAllSessions(int userId) {
+ final int callingUid = Binder.getCallingUid();
mPermissionManager.enforceCrossUserPermission(
- Binder.getCallingUid(), userId, true, false, "getAllSessions");
+ callingUid, userId, true, false, "getAllSessions");
final List<SessionInfo> result = new ArrayList<>();
synchronized (mSessions) {
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
if (session.userId == userId && !session.hasParentSessionId()) {
- result.add(session.generateInfo(false));
+ result.add(session.generateInfoForCaller(false, callingUid));
}
}
}
@@ -842,7 +846,8 @@
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
- SessionInfo info = session.generateInfo(false);
+ SessionInfo info =
+ session.generateInfoForCaller(false /*withIcon*/, Process.SYSTEM_UID);
if (Objects.equals(info.getInstallerPackageName(), installerPackageName)
&& session.userId == userId && !session.hasParentSessionId()) {
result.add(info);
@@ -1302,7 +1307,10 @@
session.markUpdated();
writeSessionsAsync();
if (mOkToSendBroadcasts) {
- mPm.sendSessionUpdatedBroadcast(session.generateInfo(false),
+ // we don't scrub the data here as this is sent only to the installer several
+ // privileged system packages
+ mPm.sendSessionUpdatedBroadcast(
+ session.generateInfoForCaller(false/*icon*/, Process.SYSTEM_UID),
session.userId);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 97aa79d..483f83e 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -557,11 +557,41 @@
}
}
- public SessionInfo generateInfo() {
- return generateInfo(true);
+ /**
+ * Returns {@code true} if the {@link SessionInfo} object should be produced with potentially
+ * sensitive data scrubbed from its fields.
+ *
+ * @param callingUid the uid of the caller; the recipient of the {@link SessionInfo} that may
+ * need to be scrubbed
+ */
+ private boolean shouldScrubData(int callingUid) {
+ return !(callingUid < Process.FIRST_APPLICATION_UID || getInstallerUid() == callingUid);
}
- public SessionInfo generateInfo(boolean includeIcon) {
+ /**
+ * Generates a {@link SessionInfo} object for the provided uid. This may result in some fields
+ * that may contain sensitive info being filtered.
+ *
+ * @param includeIcon true if the icon should be included in the object
+ * @param callingUid the uid of the caller; the recipient of the {@link SessionInfo} that may
+ * need to be scrubbed
+ * @see #shouldScrubData(int)
+ */
+ public SessionInfo generateInfoForCaller(boolean includeIcon, int callingUid) {
+ return generateInfoInternal(includeIcon, shouldScrubData(callingUid));
+ }
+
+ /**
+ * Generates a {@link SessionInfo} object to ensure proper hiding of sensitive fields.
+ *
+ * @param includeIcon true if the icon should be included in the object
+ * @see #generateInfoForCaller(boolean, int)
+ */
+ public SessionInfo generateInfoScrubbed(boolean includeIcon) {
+ return generateInfoInternal(includeIcon, true /*scrubData*/);
+ }
+
+ private SessionInfo generateInfoInternal(boolean includeIcon, boolean scrubData) {
final SessionInfo info = new SessionInfo();
synchronized (mLock) {
info.sessionId = sessionId;
@@ -584,9 +614,13 @@
info.appLabel = params.appLabel;
info.installLocation = params.installLocation;
- info.originatingUri = params.originatingUri;
+ if (!scrubData) {
+ info.originatingUri = params.originatingUri;
+ }
info.originatingUid = params.originatingUid;
- info.referrerUri = params.referrerUri;
+ if (!scrubData) {
+ info.referrerUri = params.referrerUri;
+ }
info.grantedRuntimePermissions = params.grantedRuntimePermissions;
info.whitelistedRestrictedPermissions = params.whitelistedRestrictedPermissions;
info.installFlags = params.installFlags;
@@ -2664,7 +2698,7 @@
final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING);
if (success && isNewInstall && mPm.mInstallerService.okToSendBroadcasts()
&& (params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
- mPm.sendSessionCommitBroadcast(generateInfo(), userId);
+ mPm.sendSessionCommitBroadcast(generateInfoScrubbed(true /*icon*/), userId);
}
mCallback.onSessionFinished(this, success);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 799ce65..61bf5f0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11514,8 +11514,8 @@
"Static shared libs cannot declare permission groups");
}
- // Static shared libs cannot declare features
- if (!pkg.getFeatures().isEmpty()) {
+ // Static shared libs cannot declare attributions
+ if (!pkg.getAttributions().isEmpty()) {
throw new PackageManagerException(
"Static shared libs cannot declare features");
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 83fe556..342c907 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -128,11 +128,12 @@
}
}
- ParceledListSlice<PackageInstaller.SessionInfo> getSessions() {
+ ParceledListSlice<PackageInstaller.SessionInfo> getSessions(int callingUid) {
final List<PackageInstaller.SessionInfo> result = new ArrayList<>();
synchronized (mStagedSessions) {
for (int i = 0; i < mStagedSessions.size(); i++) {
- result.add(mStagedSessions.valueAt(i).generateInfo(false));
+ final PackageInstallerSession stagedSession = mStagedSessions.valueAt(i);
+ result.add(stagedSession.generateInfoForCaller(false /*icon*/, callingUid));
}
}
return new ParceledListSlice<>(result);
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index d3f668c..0e294f70 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -391,8 +391,9 @@
ArrayMap<String, ProcessInfo> retProcs = new ArrayMap<>(numProcs);
for (String key : procs.keySet()) {
ParsedProcess proc = procs.get(key);
- retProcs.put(proc.getName(), new ProcessInfo(proc.getName(),
- new ArraySet<>(proc.getDeniedPermissions())));
+ retProcs.put(proc.getName(),
+ new ProcessInfo(proc.getName(), new ArraySet<>(proc.getDeniedPermissions()),
+ proc.getEnableGwpAsan()));
}
return retProcs;
}
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
index 7929579..46b08df 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
@@ -25,7 +25,7 @@
import android.content.pm.PermissionGroupInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.parsing.ParsingPackageRead;
-import android.content.pm.parsing.component.ParsedFeature;
+import android.content.pm.parsing.component.ParsedAttribution;
import android.content.pm.parsing.component.ParsedIntentInfo;
import android.content.pm.parsing.component.ParsedPermissionGroup;
import android.os.Bundle;
@@ -147,7 +147,7 @@
List<ParsedPermissionGroup> getPermissionGroups();
@NonNull
- List<ParsedFeature> getFeatures();
+ List<ParsedAttribution> getAttributions();
/**
* Used to determine the default preferred handler of an {@link Intent}.
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 1b5cc6a..64edacd 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5202,7 +5202,7 @@
if (dock != null) {
int result = ActivityTaskManager.getService()
.startActivityAsUser(null, mContext.getBasePackageName(),
- mContext.getFeatureId(), dock,
+ mContext.getAttributionTag(), dock,
dock.resolveTypeIfNeeded(mContext.getContentResolver()),
null, null, 0,
ActivityManager.START_FLAG_ONLY_IF_NEEDED,
@@ -5214,7 +5214,7 @@
}
int result = ActivityTaskManager.getService()
.startActivityAsUser(null, mContext.getBasePackageName(),
- mContext.getFeatureId(), mHomeIntent,
+ mContext.getAttributionTag(), mHomeIntent,
mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
null, null, 0,
ActivityManager.START_FLAG_ONLY_IF_NEEDED,
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 98579af..7f7d668 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -406,8 +406,8 @@
case FrameworkStatsLog.BATTERY_VOLTAGE:
case FrameworkStatsLog.BATTERY_CYCLE_COUNT:
return pullHealthHal(atomTag, data);
- case FrameworkStatsLog.APP_FEATURES_OPS:
- return pullAppFeaturesOps(atomTag, data);
+ case FrameworkStatsLog.ATTRIBUTED_APP_OPS:
+ return pullAttributedAppOps(atomTag, data);
default:
throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
}
@@ -562,7 +562,7 @@
registerAppsOnExternalStorageInfo();
registerFaceSettings();
registerAppOps();
- registerAppFeaturesOps();
+ registerAttributedAppOps();
registerRuntimeAppOpAccessMessage();
registerNotificationRemoteViews();
registerDangerousPermissionState();
@@ -2898,8 +2898,8 @@
return StatsManager.PULL_SUCCESS;
}
- private void registerAppFeaturesOps() {
- int tagId = FrameworkStatsLog.APP_FEATURES_OPS;
+ private void registerAttributedAppOps() {
+ int tagId = FrameworkStatsLog.ATTRIBUTED_APP_OPS;
mStatsManager.setPullAtomCallback(
tagId,
null, // use default PullAtomMetadata values
@@ -2908,7 +2908,7 @@
);
}
- int pullAppFeaturesOps(int atomTag, List<StatsEvent> pulledData) {
+ int pullAttributedAppOps(int atomTag, List<StatsEvent> pulledData) {
final long token = Binder.clearCallingIdentity();
try {
AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
@@ -2946,7 +2946,7 @@
appOps.getHistoricalOps(histOpsRequest, mContext.getMainExecutor(), ops::complete);
HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
TimeUnit.MILLISECONDS);
- return processHistoricalOps(histOps, FrameworkStatsLog.APP_FEATURES_OPS, null);
+ return processHistoricalOps(histOps, FrameworkStatsLog.ATTRIBUTED_APP_OPS, null);
}
int processHistoricalOps(HistoricalOps histOps, int atomTag, List<StatsEvent> pulledData) {
@@ -2956,15 +2956,15 @@
final int uid = uidOps.getUid();
for (int pkgIdx = 0; pkgIdx < uidOps.getPackageCount(); pkgIdx++) {
final HistoricalPackageOps packageOps = uidOps.getPackageOpsAt(pkgIdx);
- if (atomTag == FrameworkStatsLog.APP_FEATURES_OPS) {
- for (int featureIdx = 0; featureIdx < packageOps.getFeatureCount();
- featureIdx++) {
- final AppOpsManager.HistoricalFeatureOps featureOps =
- packageOps.getFeatureOpsAt(featureIdx);
- for (int opIdx = 0; opIdx < featureOps.getOpCount(); opIdx++) {
- final AppOpsManager.HistoricalOp op = featureOps.getOpAt(opIdx);
+ if (atomTag == FrameworkStatsLog.ATTRIBUTED_APP_OPS) {
+ for (int attributionIdx = 0;
+ attributionIdx < packageOps.getAttributedOpsCount(); attributionIdx++) {
+ final AppOpsManager.AttributedHistoricalOps attributedOps =
+ packageOps.getAttributedOpsAt(attributionIdx);
+ for (int opIdx = 0; opIdx < attributedOps.getOpCount(); opIdx++) {
+ final AppOpsManager.HistoricalOp op = attributedOps.getOpAt(opIdx);
counter += processHistoricalOp(op, atomTag, pulledData, uid,
- packageOps.getPackageName(), featureOps.getFeatureId());
+ packageOps.getPackageName(), attributedOps.getTag());
}
}
} else if (atomTag == FrameworkStatsLog.APP_OPS) {
@@ -2981,18 +2981,19 @@
private int processHistoricalOp(AppOpsManager.HistoricalOp op, int atomTag,
@Nullable List<StatsEvent> pulledData, int uid, String packageName,
- @Nullable String feature) {
- if (atomTag == FrameworkStatsLog.APP_FEATURES_OPS) {
+ @Nullable String attributionTag) {
+ if (atomTag == FrameworkStatsLog.ATTRIBUTED_APP_OPS) {
if (pulledData == null) { // this is size estimation call
if (op.getForegroundAccessCount(OP_FLAGS_PULLED) + op.getBackgroundAccessCount(
OP_FLAGS_PULLED) == 0) {
return 0;
} else {
- return 32 + packageName.length() + (feature == null ? 1 : feature.length());
+ return 32 + packageName.length() + (attributionTag == null ? 1
+ : attributionTag.length());
}
} else {
- if (abs((op.getOpCode() + feature + packageName).hashCode() + RANDOM_SEED) % 100
- >= mAppOpsSamplingRate) {
+ if (abs((op.getOpCode() + attributionTag + packageName).hashCode() + RANDOM_SEED)
+ % 100 >= mAppOpsSamplingRate) {
return 0;
}
}
@@ -3002,10 +3003,10 @@
e.setAtomId(atomTag);
e.writeInt(uid);
e.writeString(packageName);
- if (atomTag == FrameworkStatsLog.APP_FEATURES_OPS) {
- e.writeString(feature);
+ if (atomTag == FrameworkStatsLog.ATTRIBUTED_APP_OPS) {
+ e.writeString(attributionTag);
}
- if (atomTag == FrameworkStatsLog.APP_FEATURES_OPS) {
+ if (atomTag == FrameworkStatsLog.ATTRIBUTED_APP_OPS) {
e.writeString(op.getOpName());
} else {
e.writeInt(op.getOpCode());
@@ -3032,7 +3033,7 @@
e.writeBoolean(false);
}
}
- if (atomTag == FrameworkStatsLog.APP_FEATURES_OPS) {
+ if (atomTag == FrameworkStatsLog.ATTRIBUTED_APP_OPS) {
e.writeInt(mAppOpsSamplingRate);
}
pulledData.add(e.build());
@@ -3055,10 +3056,10 @@
e.writeInt(message.getUid());
e.writeString(message.getPackageName());
e.writeString(message.getOp());
- if (message.getFeatureId() == null) {
+ if (message.getAttributionTag() == null) {
e.writeString("");
} else {
- e.writeString(message.getFeatureId());
+ e.writeString(message.getAttributionTag());
}
e.writeString(message.getMessage());
e.writeInt(message.getSamplingStrategy());
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 04d551d..b43d8b7 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
@@ -24,6 +24,8 @@
import android.media.tv.tunerresourcemanager.IResourcesReclaimListener;
import android.media.tv.tunerresourcemanager.ITunerResourceManager;
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
+import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
+import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
@@ -189,6 +191,24 @@
}
@Override
+ public boolean requestDemux(@NonNull TunerDemuxRequest request,
+ @NonNull int[] demuxHandle) {
+ if (DEBUG) {
+ Slog.d(TAG, "requestDemux(request=" + request + ")");
+ }
+ return true;
+ }
+
+ @Override
+ public boolean requestDescrambler(@NonNull TunerDescramblerRequest request,
+ @NonNull int[] descrambleHandle) {
+ if (DEBUG) {
+ Slog.d(TAG, "requestDescrambler(request=" + request + ")");
+ }
+ return true;
+ }
+
+ @Override
public boolean requestCasSession(
@NonNull CasSessionRequest request, @NonNull int[] sessionResourceId) {
if (DEBUG) {
@@ -214,6 +234,20 @@
}
@Override
+ public void releaseDemux(int demuxHandle) {
+ if (DEBUG) {
+ Slog.d(TAG, "releaseDemux(demuxHandle=" + demuxHandle + ")");
+ }
+ }
+
+ @Override
+ public void releaseDescrambler(int descramblerHandle) {
+ if (DEBUG) {
+ Slog.d(TAG, "releaseDescrambler(descramblerHandle=" + descramblerHandle + ")");
+ }
+ }
+
+ @Override
public void releaseCasSession(int sessionResourceId) {
if (DEBUG) {
Slog.d(TAG, "releaseCasSession(sessionResourceId=" + sessionResourceId + ")");
diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java
index 761fbf8..88a60dd 100644
--- a/services/core/java/com/android/server/twilight/TwilightService.java
+++ b/services/core/java/com/android/server/twilight/TwilightService.java
@@ -50,7 +50,7 @@
implements AlarmManager.OnAlarmListener, Handler.Callback, LocationListener {
private static final String TAG = "TwilightService";
- private static final String FEATURE_ID = "TwilightService";
+ private static final String ATTRIBUTION_TAG = "TwilightService";
private static final boolean DEBUG = false;
private static final int MSG_START_LISTENING = 1;
@@ -74,7 +74,7 @@
protected TwilightState mLastTwilightState;
public TwilightService(Context context) {
- super(context.createFeatureContext(FEATURE_ID));
+ super(context.createAttributionContext(ATTRIBUTION_TAG));
mHandler = new Handler(Looper.getMainLooper(), this);
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 6eb3c0f..a298b89 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -2184,47 +2184,6 @@
}
}
- /**
- * Called when the wallpaper needs to zoom out.
- *
- * @param zoom from 0 to 1 (inclusive) where 1 means fully zoomed out, 0 means fully zoomed in.
- * @param callingPackage package name calling this API.
- * @param displayId id of the display whose zoom is updating.
- */
- public void setWallpaperZoomOut(float zoom, String callingPackage, int displayId) {
- if (!isWallpaperSupported(callingPackage)) {
- return;
- }
- synchronized (mLock) {
- if (!isValidDisplay(displayId)) {
- throw new IllegalArgumentException("Cannot find display with id=" + displayId);
- }
- int userId = UserHandle.getCallingUserId();
- if (mCurrentUserId != userId) {
- return; // Don't change the properties now
- }
- WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
- if (zoom < 0 || zoom > 1f) {
- throw new IllegalArgumentException("zoom must be between 0 and one: " + zoom);
- }
-
- if (wallpaper.connection != null) {
- final WallpaperConnection.DisplayConnector connector = wallpaper.connection
- .getDisplayConnectorOrCreate(displayId);
- final IWallpaperEngine engine = connector != null ? connector.mEngine : null;
- if (engine != null) {
- try {
- engine.setZoomOut(zoom);
- } catch (RemoteException e) {
- if (DEBUG) {
- Slog.w(TAG, "Couldn't set wallpaper zoom", e);
- }
- }
- }
- }
- }
- }
-
@Deprecated
@Override
public ParcelFileDescriptor getWallpaper(String callingPkg, IWallpaperManagerCallback cb,
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 9bad799..4ebb423 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -153,7 +153,6 @@
import android.util.proto.ProtoOutputStream;
import android.view.Display;
import android.view.DisplayInfo;
-import android.view.ITaskOrganizer;
import android.view.SurfaceControl;
import com.android.internal.annotations.GuardedBy;
@@ -307,8 +306,6 @@
// TODO(task-hierarchy): remove when tiles can be actual parents
TaskTile mTile = null;
- private int mLastTaskOrganizerWindowingMode = -1;
-
private final Handler mHandler;
private class ActivityStackHandler extends Handler {
@@ -635,8 +632,6 @@
super.onConfigurationChanged(newParentConfig);
- updateTaskOrganizerState();
-
// Only need to update surface size here since the super method will handle updating
// surface position.
updateSurfaceSize(getPendingTransaction());
@@ -692,30 +687,6 @@
}
}
- void updateTaskOrganizerState() {
- if (!isRootTask()) {
- return;
- }
-
- final int windowingMode = getWindowingMode();
- if (windowingMode == mLastTaskOrganizerWindowingMode) {
- // If our windowing mode hasn't actually changed, then just stick
- // with our old organizer. This lets us implement the semantic
- // where SysUI can continue to manage it's old tasks
- // while CTS temporarily takes over the registration.
- return;
- }
- /*
- * Different windowing modes may be managed by different task organizers. If
- * getTaskOrganizer returns null, we still call setTaskOrganizer to
- * make sure we clear it.
- */
- final ITaskOrganizer org =
- mWmService.mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
- setTaskOrganizer(org);
- mLastTaskOrganizerWindowingMode = windowingMode;
- }
-
@Override
public void setWindowingMode(int windowingMode) {
// Calling Task#setWindowingMode() for leaf task since this is the a specialization of
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 21d300a..7bacc42 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -356,6 +356,8 @@
ActivityManagerInternal mAmInternal;
UriGrantsManagerInternal mUgmInternal;
private PackageManagerInternal mPmInternal;
+ /** The cached sys ui service component name from package manager. */
+ private ComponentName mSysUiServiceComponent;
private PermissionPolicyInternal mPermissionPolicyInternal;
@VisibleForTesting
final ActivityTaskManagerInternal mInternal;
@@ -5869,6 +5871,14 @@
return mPmInternal;
}
+ ComponentName getSysUiServiceComponentLocked() {
+ if (mSysUiServiceComponent == null) {
+ final PackageManagerInternal pm = getPackageManagerInternalLocked();
+ mSysUiServiceComponent = pm.getSystemUiServiceComponent();
+ }
+ return mSysUiServiceComponent;
+ }
+
PermissionPolicyInternal getPermissionPolicyInternal() {
if (mPermissionPolicyInternal == null) {
mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 36fdb2d..98e3d07 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2224,9 +2224,7 @@
.addTaggedData(MetricsEvent.FIELD_DISPLAY_ID, getDisplayId()));
}
- // If there was no pinned stack, we still need to notify the controller of the display info
- // update as a result of the config change.
- if (mPinnedStackControllerLocked != null && !hasPinnedTask()) {
+ if (mPinnedStackControllerLocked != null) {
mPinnedStackControllerLocked.onDisplayInfoChanged(getDisplayInfo());
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index a094c81..ba61667 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -440,10 +440,12 @@
updateDreamingSleepToken(msg.arg1 != 0);
break;
case MSG_REQUEST_TRANSIENT_BARS:
- WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS)
- ? mStatusBar : mNavigationBar;
- if (targetBar != null) {
- requestTransientBars(targetBar);
+ synchronized (mLock) {
+ WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS)
+ ? mStatusBar : mNavigationBar;
+ if (targetBar != null) {
+ requestTransientBars(targetBar);
+ }
}
break;
case MSG_DISPOSE_INPUT_CONSUMER:
@@ -499,15 +501,20 @@
new SystemGesturesPointerEventListener.Callbacks() {
@Override
public void onSwipeFromTop() {
- if (mStatusBar != null) {
- requestTransientBars(mStatusBar);
+ synchronized (mLock) {
+ if (mStatusBar != null) {
+ requestTransientBars(mStatusBar);
+ }
}
}
@Override
public void onSwipeFromBottom() {
- if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) {
- requestTransientBars(mNavigationBar);
+ synchronized (mLock) {
+ if (mNavigationBar != null
+ && mNavigationBarPosition == NAV_BAR_BOTTOM) {
+ requestTransientBars(mNavigationBar);
+ }
}
}
@@ -517,12 +524,13 @@
synchronized (mLock) {
mDisplayContent.calculateSystemGestureExclusion(
excludedRegion, null /* outUnrestricted */);
- }
- final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
- || mNavigationBarPosition == NAV_BAR_RIGHT;
- if (mNavigationBar != null && sideAllowed
- && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
- requestTransientBars(mNavigationBar);
+ final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
+ || mNavigationBarPosition == NAV_BAR_RIGHT;
+ if (mNavigationBar != null && sideAllowed
+ && !mSystemGestures.currentGestureStartedInRegion(
+ excludedRegion)) {
+ requestTransientBars(mNavigationBar);
+ }
}
excludedRegion.recycle();
}
@@ -533,12 +541,13 @@
synchronized (mLock) {
mDisplayContent.calculateSystemGestureExclusion(
excludedRegion, null /* outUnrestricted */);
- }
- final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
- || mNavigationBarPosition == NAV_BAR_LEFT;
- if (mNavigationBar != null && sideAllowed
- && !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
- requestTransientBars(mNavigationBar);
+ final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
+ || mNavigationBarPosition == NAV_BAR_LEFT;
+ if (mNavigationBar != null && sideAllowed
+ && !mSystemGestures.currentGestureStartedInRegion(
+ excludedRegion)) {
+ requestTransientBars(mNavigationBar);
+ }
}
excludedRegion.recycle();
}
@@ -3156,47 +3165,46 @@
}
private void requestTransientBars(WindowState swipeTarget) {
- synchronized (mLock) {
- if (!mService.mPolicy.isUserSetupComplete()) {
- // Swipe-up for navigation bar is disabled during setup
+ if (!mService.mPolicy.isUserSetupComplete()) {
+ // Swipe-up for navigation bar is disabled during setup
+ return;
+ }
+ if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
+ if (swipeTarget == mNavigationBar
+ && !getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)) {
+ // Don't show status bar when swiping on already visible navigation bar
return;
}
- if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
- if (swipeTarget == mNavigationBar
- && !getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)) {
- // Don't show status bar when swiping on already visible navigation bar
- return;
- }
- final InsetsControlTarget controlTarget =
- swipeTarget.getControllableInsetProvider().getControlTarget();
+ final InsetsSourceProvider provider = swipeTarget.getControllableInsetProvider();
+ final InsetsControlTarget controlTarget = provider != null
+ ? provider.getControlTarget() : null;
- // No transient mode on lockscreen (in notification shade window).
- if (controlTarget == null || controlTarget == getNotificationShade()) {
+ // No transient mode on lockscreen (in notification shade window).
+ if (controlTarget == null || controlTarget == getNotificationShade()) {
+ return;
+ }
+ if (controlTarget.canShowTransient()) {
+ mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
+ new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
+ } else {
+ controlTarget.showInsets(Type.systemBars(), false);
+ }
+ } else {
+ boolean sb = mStatusBarController.checkShowTransientBarLw();
+ boolean nb = mNavigationBarController.checkShowTransientBarLw()
+ && !isNavBarEmpty(mLastSystemUiFlags);
+ if (sb || nb) {
+ // Don't show status bar when swiping on already visible navigation bar
+ if (!nb && swipeTarget == mNavigationBar) {
+ if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
return;
}
- if (controlTarget.canShowTransient()) {
- mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
- new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR}));
- } else {
- controlTarget.showInsets(Type.systemBars(), false);
- }
- } else {
- boolean sb = mStatusBarController.checkShowTransientBarLw();
- boolean nb = mNavigationBarController.checkShowTransientBarLw()
- && !isNavBarEmpty(mLastSystemUiFlags);
- if (sb || nb) {
- // Don't show status bar when swiping on already visible navigation bar
- if (!nb && swipeTarget == mNavigationBar) {
- if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
- return;
- }
- if (sb) mStatusBarController.showTransient();
- if (nb) mNavigationBarController.showTransient();
- updateSystemUiVisibilityLw();
- }
+ if (sb) mStatusBarController.showTransient();
+ if (nb) mNavigationBarController.showTransient();
+ updateSystemUiVisibilityLw();
}
- mImmersiveModeConfirmation.confirmCurrentPrompt();
}
+ mImmersiveModeConfirmation.confirmCurrentPrompt();
}
private void disposeInputConsumer(InputConsumer inputConsumer) {
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 01f9888..958c8af 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -36,6 +36,7 @@
import android.util.SparseArray;
import android.view.InsetsAnimationControlCallbacks;
import android.view.InsetsAnimationControlImpl;
+import android.view.InsetsAnimationControlRunner;
import android.view.InsetsController;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
@@ -44,6 +45,7 @@
import android.view.SyncRtSurfaceTransactionApplier;
import android.view.ViewRootImpl;
import android.view.WindowInsetsAnimation;
+import android.view.WindowInsetsAnimation.Bounds;
import android.view.WindowInsetsAnimationControlListener;
import com.android.internal.annotations.VisibleForTesting;
@@ -327,7 +329,7 @@
InsetsPolicyAnimationControlCallbacks mControlCallbacks;
InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback) {
- super(show);
+ super(show, true /* useSfVsync */);
mFinishCallback = finishCallback;
mControlCallbacks = new InsetsPolicyAnimationControlCallbacks(this);
}
@@ -360,8 +362,6 @@
mFocusedWin.getDisplayContent().getBounds(), getState(),
mListener, typesReady, this, mListener.getDurationMs(),
InsetsController.INTERPOLATOR, true,
- show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN
- : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN,
show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE);
SurfaceAnimationThread.getHandler().post(
() -> mListener.onReady(mAnimationControl, typesReady));
@@ -377,7 +377,7 @@
}
@Override
- public void notifyFinished(InsetsAnimationControlImpl controller, boolean shown) {
+ public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) {
// Nothing's needed here. Finish steps is handled in the listener
// onAnimationFinished callback.
}
@@ -406,14 +406,14 @@
applyParams(t, surfaceParams, mTmpFloat9);
}
t.apply();
+ t.close();
}
@Override
public void startAnimation(InsetsAnimationControlImpl controller,
WindowInsetsAnimationControlListener listener, int types,
WindowInsetsAnimation animation,
- WindowInsetsAnimation.Bounds bounds,
- int layoutDuringAnimation) {
+ Bounds bounds) {
}
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 6ff029b..ee36db9 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_UNDEFINED;
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_INVALID;
@@ -29,6 +30,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.WindowConfiguration;
+import android.app.WindowConfiguration.WindowingMode;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseArray;
@@ -74,30 +77,28 @@
/**
* When dispatching window state to the client, we'll need to exclude the source that represents
- * the window that is being dispatched.
+ * the window that is being dispatched. We also need to exclude certain types of insets source
+ * for client within specific windowing modes.
*
* @param target The client we dispatch the state to.
* @return The state stripped of the necessary information.
*/
InsetsState getInsetsForDispatch(@NonNull WindowState target) {
final InsetsSourceProvider provider = target.getControllableInsetProvider();
- if (provider == null) {
- return mState;
- }
- final @InternalInsetsType int type = provider.getSource().getType();
- return getInsetsForType(type);
+ final @InternalInsetsType int type = provider != null
+ ? provider.getSource().getType() : ITYPE_INVALID;
+ return getInsetsForTypeAndWindowingMode(type, target.getWindowingMode());
}
InsetsState getInsetsForWindowMetrics(@NonNull WindowManager.LayoutParams attrs) {
final @InternalInsetsType int type = getInsetsTypeForWindowType(attrs.type);
- if (type == ITYPE_INVALID) {
- return mState;
- }
- return getInsetsForType(type);
+ final WindowToken token = mDisplayContent.getWindowToken(attrs.token);
+ final @WindowingMode int windowingMode = token != null
+ ? token.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
+ return getInsetsForTypeAndWindowingMode(type, windowingMode);
}
- @InternalInsetsType
- private static int getInsetsTypeForWindowType(int type) {
+ private static @InternalInsetsType int getInsetsTypeForWindowType(int type) {
switch(type) {
case TYPE_STATUS_BAR:
return ITYPE_STATUS_BAR;
@@ -110,36 +111,48 @@
}
}
- private InsetsState getInsetsForType(@InternalInsetsType int type) {
- final InsetsState state = new InsetsState();
- state.set(mState);
- state.removeSource(type);
+ /** @see #getInsetsForDispatch */
+ private InsetsState getInsetsForTypeAndWindowingMode(@InternalInsetsType int type,
+ @WindowingMode int windowingMode) {
+ InsetsState state = mState;
- // Navigation bar doesn't get influenced by anything else
- if (type == ITYPE_NAVIGATION_BAR) {
- state.removeSource(ITYPE_IME);
- state.removeSource(ITYPE_STATUS_BAR);
- state.removeSource(ITYPE_CAPTION_BAR);
- }
+ if (type != ITYPE_INVALID) {
+ state = new InsetsState(state);
+ state.removeSource(type);
- // Status bar doesn't get influenced by caption bar
- if (type == ITYPE_STATUS_BAR) {
- state.removeSource(ITYPE_CAPTION_BAR);
- }
+ // Navigation bar doesn't get influenced by anything else
+ if (type == ITYPE_NAVIGATION_BAR) {
+ state.removeSource(ITYPE_IME);
+ state.removeSource(ITYPE_STATUS_BAR);
+ state.removeSource(ITYPE_CAPTION_BAR);
+ }
- // IME needs different frames for certain cases (e.g. navigation bar in gesture nav).
- if (type == ITYPE_IME) {
- for (int i = mProviders.size() - 1; i >= 0; i--) {
- InsetsSourceProvider otherProvider = mProviders.valueAt(i);
- if (otherProvider.overridesImeFrame()) {
- InsetsSource override =
- new InsetsSource(state.getSource(otherProvider.getSource().getType()));
- override.setFrame(otherProvider.getImeOverrideFrame());
- state.addSource(override);
+ // Status bar doesn't get influenced by caption bar
+ if (type == ITYPE_STATUS_BAR) {
+ state.removeSource(ITYPE_CAPTION_BAR);
+ }
+
+ // IME needs different frames for certain cases (e.g. navigation bar in gesture nav).
+ if (type == ITYPE_IME) {
+ for (int i = mProviders.size() - 1; i >= 0; i--) {
+ InsetsSourceProvider otherProvider = mProviders.valueAt(i);
+ if (otherProvider.overridesImeFrame()) {
+ InsetsSource override =
+ new InsetsSource(
+ state.getSource(otherProvider.getSource().getType()));
+ override.setFrame(otherProvider.getImeOverrideFrame());
+ state.addSource(override);
+ }
}
}
}
+ if (WindowConfiguration.isFloating(windowingMode)) {
+ state = new InsetsState(state);
+ state.removeSource(ITYPE_STATUS_BAR);
+ state.removeSource(ITYPE_NAVIGATION_BAR);
+ }
+
return state;
}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 9df4248..5f3732a 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -356,6 +356,31 @@
}
@Override
+ public void setWallpaperZoomOut(IBinder window, float zoom) {
+ if (Float.compare(0f, zoom) > 0 || Float.compare(1f, zoom) < 0 || Float.isNaN(zoom)) {
+ throw new IllegalArgumentException("Zoom must be a valid float between 0 and 1: "
+ + zoom);
+ }
+ synchronized (mService.mGlobalLock) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ actionOnWallpaper(window, (wpController, windowState) ->
+ wpController.setWallpaperZoomOut(windowState, zoom));
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ @Override
+ public void setShouldZoomOutWallpaper(IBinder window, boolean shouldZoom) {
+ synchronized (mService.mGlobalLock) {
+ actionOnWallpaper(window, (wpController, windowState) ->
+ wpController.setShouldZoomOutWallpaper(windowState, shouldZoom));
+ }
+ }
+
+ @Override
public void wallpaperOffsetsComplete(IBinder window) {
synchronized (mService.mGlobalLock) {
actionOnWallpaper(window, (wpController, windowState) ->
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index b2db99b..8c7a68b 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -474,6 +474,7 @@
* taskAppeared callback, and emit a taskRemoved callback when the Task is vanished.
*/
ITaskOrganizer mTaskOrganizer;
+ private int mLastTaskOrganizerWindowingMode = -1;
/**
* Last Picture-in-Picture params applicable to the task. Updated when the app
@@ -1929,6 +1930,7 @@
// TODO: Should also take care of Pip mode changes here.
saveLaunchingStateIfNeeded();
+ updateTaskOrganizerState(false /* forceUpdate */);
}
/**
@@ -4018,6 +4020,39 @@
// Called on Binder death.
void taskOrganizerDied() {
mTaskOrganizer = null;
+ mLastTaskOrganizerWindowingMode = -1;
+ }
+
+ /**
+ * Called when the task state changes (ie. from windowing mode change) an the task organizer
+ * state should also be updated.
+ *
+ * @param forceUpdate Updates the task organizer to the one currently specified in the task
+ * org controller for the task's windowing mode, ignoring the cached
+ * windowing mode checks.
+ */
+ void updateTaskOrganizerState(boolean forceUpdate) {
+ if (!isRootTask()) {
+ return;
+ }
+
+ final int windowingMode = getWindowingMode();
+ if (!forceUpdate && windowingMode == mLastTaskOrganizerWindowingMode) {
+ // If our windowing mode hasn't actually changed, then just stick
+ // with our old organizer. This lets us implement the semantic
+ // where SysUI can continue to manage it's old tasks
+ // while CTS temporarily takes over the registration.
+ return;
+ }
+ /*
+ * Different windowing modes may be managed by different task organizers. If
+ * getTaskOrganizer returns null, we still call setTaskOrganizer to
+ * make sure we clear it.
+ */
+ final ITaskOrganizer org =
+ mWmService.mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
+ setTaskOrganizer(org);
+ mLastTaskOrganizerWindowingMode = windowingMode;
}
@Override
@@ -4123,8 +4158,16 @@
return mMainWindowSizeChangeTransaction;
}
+ void setActivityWindowingMode(int windowingMode) {
+ PooledConsumer c = PooledLambda.obtainConsumer(ActivityRecord::setWindowingMode,
+ PooledLambda.__(ActivityRecord.class), windowingMode);
+ forAllActivities(c);
+ c.recycle();
+ }
+
@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 4093fe5..9cbc9ee 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -105,7 +105,7 @@
TaskOrganizerState(ITaskOrganizer organizer, int windowingMode,
- TaskOrganizerState replacing) {
+ @Nullable TaskOrganizerState replacing) {
mOrganizer = organizer;
mDeathRecipient = new DeathRecipient(organizer, windowingMode);
try {
@@ -203,10 +203,27 @@
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
+ if (getTaskOrganizer(windowingMode) != null) {
+ Slog.w(TAG, "Task organizer already exists for windowing mode: "
+ + windowingMode);
+ }
+ final TaskOrganizerState previousState =
+ mTaskOrganizersForWindowingMode.get(windowingMode);
final TaskOrganizerState state = new TaskOrganizerState(organizer, windowingMode,
- mTaskOrganizersForWindowingMode.get(windowingMode));
+ previousState);
mTaskOrganizersForWindowingMode.put(windowingMode, state);
mTaskOrganizerStates.put(organizer.asBinder(), state);
+
+ if (previousState == null) {
+ // Only in the case where this is the root task organizer for the given
+ // windowing mode, we add report all existing tasks in that mode to the new
+ // task organizer.
+ mService.mRootWindowContainer.forAllTasks((task) -> {
+ if (task.getWindowingMode() == windowingMode) {
+ task.updateTaskOrganizerState(true /* forceUpdate */);
+ }
+ });
+ }
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -553,18 +570,28 @@
WindowContainerTransaction.Change c) {
int effects = sanitizeAndApplyChange(wc, c);
+ final Task tr = wc.asTask();
+
final SurfaceControl.Transaction t = c.getBoundsChangeTransaction();
if (t != null) {
- Task tr = (Task) wc;
tr.setMainWindowSizeChangeTransaction(t);
}
Rect enterPipBounds = c.getEnterPipBounds();
if (enterPipBounds != null) {
- Task tr = (Task) wc;
mService.mStackSupervisor.updatePictureInPictureMode(tr,
enterPipBounds, true);
}
+
+ final int windowingMode = c.getWindowingMode();
+ if (windowingMode > -1) {
+ tr.setWindowingMode(windowingMode);
+ }
+ final int childWindowingMode = c.getActivityWindowingMode();
+ if (childWindowingMode > -1) {
+ tr.setActivityWindowingMode(childWindowingMode);
+ }
+
return effects;
}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 669eb78..57d0a33 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -41,6 +41,7 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.ArraySet;
+import android.util.MathUtils;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.SurfaceControl;
@@ -52,6 +53,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.function.Consumer;
/**
* Controls wallpaper windows visibility, ordering, and so on.
@@ -75,8 +77,10 @@
private float mLastWallpaperY = -1;
private float mLastWallpaperXStep = -1;
private float mLastWallpaperYStep = -1;
+ private float mLastWallpaperZoomOut = 0;
private int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE;
private int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE;
+ private final float mMaxWallpaperScale;
// This is set when we are waiting for a wallpaper to tell us it is done
// changing its scroll position.
@@ -191,9 +195,21 @@
return false;
};
+ /**
+ * @see #computeLastWallpaperZoomOut()
+ */
+ private Consumer<WindowState> mComputeMaxZoomOutFunction = windowState -> {
+ if (!windowState.mIsWallpaper
+ && Float.compare(windowState.mWallpaperZoomOut, mLastWallpaperZoomOut) > 0) {
+ mLastWallpaperZoomOut = windowState.mWallpaperZoomOut;
+ }
+ };
+
WallpaperController(WindowManagerService service, DisplayContent displayContent) {
mService = service;
mDisplayContent = displayContent;
+ mMaxWallpaperScale = service.mContext.getResources()
+ .getFloat(com.android.internal.R.dimen.config_wallpaperMaxScale);
}
WindowState getWallpaperTarget() {
@@ -325,20 +341,30 @@
rawChanged = true;
}
- boolean changed = wallpaperWin.mWinAnimator.setWallpaperOffset(xOffset, yOffset);
+ if (Float.compare(wallpaperWin.mWallpaperZoomOut, mLastWallpaperZoomOut) != 0) {
+ wallpaperWin.mWallpaperZoomOut = mLastWallpaperZoomOut;
+ rawChanged = true;
+ }
+
+ boolean changed = wallpaperWin.mWinAnimator.setWallpaperOffset(xOffset, yOffset,
+ wallpaperWin.mShouldScaleWallpaper
+ ? zoomOutToScale(wallpaperWin.mWallpaperZoomOut) : 1);
if (rawChanged && (wallpaperWin.mAttrs.privateFlags &
WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
try {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
+ wallpaperWin + " x=" + wallpaperWin.mWallpaperX
- + " y=" + wallpaperWin.mWallpaperY);
+ + " y=" + wallpaperWin.mWallpaperY
+ + " zoom=" + wallpaperWin.mWallpaperZoomOut);
if (sync) {
mWaitingOnWallpaper = wallpaperWin;
}
wallpaperWin.mClient.dispatchWallpaperOffsets(
wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
- wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
+ wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep,
+ wallpaperWin.mWallpaperZoomOut, sync);
+
if (sync) {
if (mWaitingOnWallpaper != null) {
long start = SystemClock.uptimeMillis();
@@ -378,6 +404,20 @@
}
}
+ void setWallpaperZoomOut(WindowState window, float zoom) {
+ if (Float.compare(window.mWallpaperZoomOut, zoom) != 0) {
+ window.mWallpaperZoomOut = zoom;
+ updateWallpaperOffsetLocked(window, false);
+ }
+ }
+
+ void setShouldZoomOutWallpaper(WindowState window, boolean shouldZoom) {
+ if (shouldZoom != window.mShouldScaleWallpaper) {
+ window.mShouldScaleWallpaper = shouldZoom;
+ updateWallpaperOffsetLocked(window, false);
+ }
+ }
+
void setWindowWallpaperDisplayOffset(WindowState window, int x, int y) {
if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y) {
window.mWallpaperDisplayOffsetX = x;
@@ -420,6 +460,7 @@
} else if (changingTarget.mWallpaperY >= 0) {
mLastWallpaperY = changingTarget.mWallpaperY;
}
+ computeLastWallpaperZoomOut();
if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
} else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
@@ -593,6 +634,9 @@
mLastWallpaperX = mWallpaperTarget.mWallpaperX;
mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
}
+ if (mWallpaperTarget.mWallpaperZoomOut >= 0) {
+ mLastWallpaperZoomOut = mWallpaperTarget.mWallpaperZoomOut;
+ }
if (mWallpaperTarget.mWallpaperY >= 0) {
mLastWallpaperY = mWallpaperTarget.mWallpaperY;
mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
@@ -762,6 +806,23 @@
return mTmpTopWallpaper;
}
+ /**
+ * Each window can request a zoom, example:
+ * - User is in overview, zoomed out.
+ * - User also pulls down the shade.
+ *
+ * This means that we always have to choose the largest zoom out that we have, otherwise
+ * we'll have conflicts and break the "depth system" mental model.
+ */
+ private void computeLastWallpaperZoomOut() {
+ mLastWallpaperZoomOut = 0;
+ mDisplayContent.forAllWindows(mComputeMaxZoomOutFunction, true);
+ }
+
+ private float zoomOutToScale(float zoom) {
+ return MathUtils.lerp(1, mMaxWallpaperScale, 1 - zoom);
+ }
+
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("displayId="); pw.println(mDisplayContent.getDisplayId());
pw.print(prefix); pw.print("mWallpaperTarget="); pw.println(mWallpaperTarget);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index e8897e1..ec90097 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -275,7 +275,7 @@
RemoteToken mRemoteToken = null;
BLASTSyncEngine mBLASTSyncEngine = new BLASTSyncEngine();
- SurfaceControl.Transaction mBLASTSyncTransaction = new SurfaceControl.Transaction();
+ SurfaceControl.Transaction mBLASTSyncTransaction;
boolean mUsingBLASTSyncTransaction = false;
BLASTSyncEngine.TransactionReadyListener mWaitingListener;
int mWaitingSyncId;
@@ -283,6 +283,7 @@
WindowContainer(WindowManagerService wms) {
mWmService = wms;
mPendingTransaction = wms.mTransactionFactory.get();
+ mBLASTSyncTransaction = wms.mTransactionFactory.get();
mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
mSurfaceFreezer = new SurfaceFreezer(this, wms);
}
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 833bb83..32eb932 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -53,6 +53,7 @@
import android.content.res.Configuration;
import android.os.Build;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.ArraySet;
@@ -200,6 +201,9 @@
/** Whether our process is currently running a {@link IRemoteAnimationRunner} */
private boolean mRunningRemoteAnimation;
+ /** Whether this process is owned by the System UI package. */
+ final boolean mIsSysUiPackage;
+
public WindowProcessController(@NonNull ActivityTaskManagerService atm, ApplicationInfo info,
String name, int uid, int userId, Object owner, WindowProcessListener listener) {
mInfo = info;
@@ -210,6 +214,10 @@
mListener = listener;
mAtm = atm;
mDisplayId = INVALID_DISPLAY;
+
+ mIsSysUiPackage = info.packageName.equals(
+ mAtm.getSysUiServiceComponentLocked().getPackageName());
+
onConfigurationChanged(atm.getGlobalConfiguration());
}
@@ -1077,6 +1085,12 @@
* always track the configuration of the non-finishing activity last added to the process.
*/
private void updateActivityConfigurationListener() {
+ if (mIsSysUiPackage || mUid == Process.SYSTEM_UID) {
+ // This is a system owned process and should not use an activity config.
+ // TODO(b/151161907): Remove after support for display-independent (raw) SysUi configs.
+ return;
+ }
+
for (int i = mActivities.size() - 1; i >= 0; i--) {
final ActivityRecord activityRecord = mActivities.get(i);
if (!activityRecord.finishing && !activityRecord.containsListener(this)) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index fc28cd5..c44be4d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -415,6 +415,7 @@
float mHScale=1, mVScale=1;
float mLastHScale=1, mLastVScale=1;
final Matrix mTmpMatrix = new Matrix();
+ final float[] mTmpMatrixArray = new float[9];
private final WindowFrames mWindowFrames = new WindowFrames();
@@ -446,6 +447,14 @@
float mWallpaperX = -1;
float mWallpaperY = -1;
+ // If a window showing a wallpaper: the requested zoom out for the
+ // wallpaper; if a wallpaper window: the currently applied zoom.
+ float mWallpaperZoomOut = -1;
+
+ // If a wallpaper window: whether the wallpaper should be scaled when zoomed, if set
+ // to false, mWallpaperZoom will be ignored here and just passed to the WallpaperService.
+ boolean mShouldScaleWallpaper;
+
// If a window showing a wallpaper: what fraction of the offset
// range corresponds to a full virtual screen.
float mWallpaperXStep = -1;
@@ -3923,6 +3932,9 @@
pw.println(prefix + "mWallpaperXStep=" + mWallpaperXStep
+ " mWallpaperYStep=" + mWallpaperYStep);
}
+ if (mWallpaperZoomOut != -1) {
+ pw.println(prefix + "mWallpaperZoomOut=" + mWallpaperZoomOut);
+ }
if (mWallpaperDisplayOffsetX != Integer.MIN_VALUE
|| mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
pw.println(prefix + "mWallpaperDisplayOffsetX=" + mWallpaperDisplayOffsetX
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 79dc536..563710b 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -16,6 +16,12 @@
package com.android.server.wm;
+import static android.graphics.Matrix.MSCALE_X;
+import static android.graphics.Matrix.MSCALE_Y;
+import static android.graphics.Matrix.MSKEW_X;
+import static android.graphics.Matrix.MSKEW_Y;
+import static android.graphics.Matrix.MTRANS_X;
+import static android.graphics.Matrix.MTRANS_Y;
import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
@@ -217,6 +223,10 @@
int mXOffset = 0;
int mYOffset = 0;
+ // A scale factor for the surface contents, that will be applied from the center of the visible
+ // region.
+ float mWallpaperScale = 1f;
+
/**
* A flag to determine if the WSA needs to offset its position to compensate for the stack's
* position update before the WSA surface has resized.
@@ -1034,7 +1044,12 @@
}
}
}
- mSurfaceController.setPositionInTransaction(xOffset, yOffset, recoveringMemory);
+ if (!mIsWallpaper) {
+ mSurfaceController.setPositionInTransaction(xOffset, yOffset, recoveringMemory);
+ } else {
+ setWallpaperPositionAndScale(
+ xOffset, yOffset, mWallpaperScale, recoveringMemory);
+ }
}
}
@@ -1051,11 +1066,15 @@
if (!w.mSeamlesslyRotated) {
- applyCrop(clipRect, recoveringMemory);
- mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * mExtraHScale,
- mDtDx * w.mVScale * mExtraVScale,
- mDtDy * w.mHScale * mExtraHScale,
- mDsDy * w.mVScale * mExtraVScale, recoveringMemory);
+ if (!mIsWallpaper) {
+ applyCrop(clipRect, recoveringMemory);
+ mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * mExtraHScale,
+ mDtDx * w.mVScale * mExtraVScale,
+ mDtDy * w.mHScale * mExtraHScale,
+ mDsDy * w.mVScale * mExtraVScale, recoveringMemory);
+ } else {
+ setWallpaperPositionAndScale(mXOffset, mYOffset, mWallpaperScale, recoveringMemory);
+ }
}
if (mSurfaceResized) {
@@ -1202,18 +1221,18 @@
mSurfaceController.setTransparentRegionHint(region);
}
- boolean setWallpaperOffset(int dx, int dy) {
- if (mXOffset == dx && mYOffset == dy) {
+ boolean setWallpaperOffset(int dx, int dy, float scale) {
+ if (mXOffset == dx && mYOffset == dy && Float.compare(mWallpaperScale, scale) == 0) {
return false;
}
mXOffset = dx;
mYOffset = dy;
+ mWallpaperScale = scale;
try {
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset");
mService.openSurfaceTransaction();
- mSurfaceController.setPositionInTransaction(dx, dy, false);
- applyCrop(null, false);
+ setWallpaperPositionAndScale(dx, dy, scale, false);
} catch (RuntimeException e) {
Slog.w(TAG, "Error positioning surface of " + mWin
+ " pos=(" + dx + "," + dy + ")", e);
@@ -1225,6 +1244,27 @@
}
}
+ private void setWallpaperPositionAndScale(int dx, int dy, float scale,
+ boolean recoveringMemory) {
+ DisplayInfo displayInfo = mWin.getDisplayInfo();
+ Matrix matrix = mWin.mTmpMatrix;
+ matrix.setTranslate(dx, dy);
+ matrix.postScale(scale, scale, displayInfo.logicalWidth / 2f,
+ displayInfo.logicalHeight / 2f);
+ matrix.getValues(mWin.mTmpMatrixArray);
+ matrix.reset();
+
+ mSurfaceController.setPositionInTransaction(mWin.mTmpMatrixArray[MTRANS_X],
+ mWin.mTmpMatrixArray[MTRANS_Y], recoveringMemory);
+ mSurfaceController.setMatrixInTransaction(
+ mDsDx * mWin.mTmpMatrixArray[MSCALE_X] * mWin.mHScale * mExtraHScale,
+ mDtDx * mWin.mTmpMatrixArray[MSKEW_Y] * mWin.mVScale * mExtraVScale,
+ mDtDy * mWin.mTmpMatrixArray[MSKEW_X] * mWin.mHScale * mExtraHScale,
+ mDsDy * mWin.mTmpMatrixArray[MSCALE_Y] * mWin.mVScale * mExtraVScale,
+ recoveringMemory);
+ applyCrop(null, recoveringMemory);
+ }
+
/**
* Try to change the pixel format without recreating the surface. This
* will be common in the case of changing from PixelFormat.OPAQUE to
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 312d2d2..6f41631 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -86,6 +86,7 @@
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
+import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
import static android.provider.Telephony.Carriers.DPC_URI;
@@ -1198,7 +1199,7 @@
// Whether the admin explicitly requires personal apps to be suspended
boolean mSuspendPersonalApps = false;
// Maximum time the profile owned by this admin can be off.
- long mProfileMaximumTimeOff = 0;
+ long mProfileMaximumTimeOffMillis = 0;
// Time by which the profile should be turned on according to System.currentTimeMillis().
long mProfileOffDeadline = 0;
@@ -1439,10 +1440,11 @@
if (mSuspendPersonalApps) {
writeAttributeValueToXml(out, TAG_SUSPEND_PERSONAL_APPS, mSuspendPersonalApps);
}
- if (mProfileMaximumTimeOff != 0) {
- writeAttributeValueToXml(out, TAG_PROFILE_MAXIMUM_TIME_OFF, mProfileMaximumTimeOff);
+ if (mProfileMaximumTimeOffMillis != 0) {
+ writeAttributeValueToXml(out, TAG_PROFILE_MAXIMUM_TIME_OFF,
+ mProfileMaximumTimeOffMillis);
}
- if (mProfileMaximumTimeOff != 0) {
+ if (mProfileMaximumTimeOffMillis != 0) {
writeAttributeValueToXml(out, TAG_PROFILE_OFF_DEADLINE, mProfileOffDeadline);
}
if (!TextUtils.isEmpty(mAlwaysOnVpnPackage)) {
@@ -1691,7 +1693,7 @@
mSuspendPersonalApps = Boolean.parseBoolean(
parser.getAttributeValue(null, ATTR_VALUE));
} else if (TAG_PROFILE_MAXIMUM_TIME_OFF.equals(tag)) {
- mProfileMaximumTimeOff =
+ mProfileMaximumTimeOffMillis =
Long.parseLong(parser.getAttributeValue(null, ATTR_VALUE));
} else if (TAG_PROFILE_OFF_DEADLINE.equals(tag)) {
mProfileOffDeadline =
@@ -1929,8 +1931,8 @@
pw.println(mCrossProfilePackages);
pw.print("mSuspendPersonalApps=");
pw.println(mSuspendPersonalApps);
- pw.print("mProfileMaximumTimeOff=");
- pw.println(mProfileMaximumTimeOff);
+ pw.print("mProfileMaximumTimeOffMillis=");
+ pw.println(mProfileMaximumTimeOffMillis);
pw.print("mProfileOffDeadline=");
pw.println(mProfileOffDeadline);
pw.print("mAlwaysOnVpnPackage=");
@@ -5874,6 +5876,14 @@
}
}
+ private void enforceNetworkStackOrProfileOrDeviceOwner(ComponentName who) {
+ if (mContext.checkCallingPermission(PERMISSION_MAINLINE_NETWORK_STACK)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ enforceProfileOrDeviceOwner(who);
+ }
+
private void enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(ComponentName who) {
synchronized (getLockObject()) {
getActiveAdminForCallerLocked(
@@ -6870,7 +6880,7 @@
@Override
public boolean isAlwaysOnVpnLockdownEnabled(ComponentName admin) throws SecurityException {
- enforceProfileOrDeviceOwner(admin);
+ enforceNetworkStackOrProfileOrDeviceOwner(admin);
final int userId = mInjector.userHandleGetCallingUserId();
return mInjector.binderWithCleanCallingIdentity(
@@ -7786,7 +7796,7 @@
* Set whether auto time is enabled on the device.
*/
@Override
- public void setAutoTime(ComponentName who, boolean enabled) {
+ public void setAutoTimeEnabled(ComponentName who, boolean enabled) {
if (!mHasFeature) {
return;
}
@@ -7807,7 +7817,7 @@
* Returns whether auto time is used on the device or not.
*/
@Override
- public boolean getAutoTime(ComponentName who) {
+ public boolean getAutoTimeEnabled(ComponentName who) {
if (!mHasFeature) {
return false;
}
@@ -7821,7 +7831,7 @@
* Set whether auto time zone is enabled on the device.
*/
@Override
- public void setAutoTimeZone(ComponentName who, boolean enabled) {
+ public void setAutoTimeZoneEnabled(ComponentName who, boolean enabled) {
if (!mHasFeature) {
return;
}
@@ -7842,7 +7852,7 @@
* Returns whether auto time zone is used on the device or not.
*/
@Override
- public boolean getAutoTimeZone(ComponentName who) {
+ public boolean getAutoTimeZoneEnabled(ComponentName who) {
if (!mHasFeature) {
return false;
}
@@ -15716,18 +15726,18 @@
}
boolean shouldSaveSettings = false;
if (profileOwner.mProfileOffDeadline != 0
- && (profileOwner.mProfileMaximumTimeOff == 0 || unlocked)) {
+ && (profileOwner.mProfileMaximumTimeOffMillis == 0 || unlocked)) {
// There is a deadline but either there is no policy or the profile is unlocked -> clear
// the deadline.
Slog.i(LOG_TAG, "Profile off deadline is reset to zero");
profileOwner.mProfileOffDeadline = 0;
shouldSaveSettings = true;
} else if (profileOwner.mProfileOffDeadline == 0
- && (profileOwner.mProfileMaximumTimeOff != 0 && !unlocked)) {
+ && (profileOwner.mProfileMaximumTimeOffMillis != 0 && !unlocked)) {
// There profile is locked and there is a policy, but the deadline is not set -> set the
// deadline.
Slog.i(LOG_TAG, "Profile off deadline is set.");
- profileOwner.mProfileOffDeadline = now + profileOwner.mProfileMaximumTimeOff;
+ profileOwner.mProfileOffDeadline = now + profileOwner.mProfileMaximumTimeOffMillis;
shouldSaveSettings = true;
}
@@ -15828,7 +15838,7 @@
}
@Override
- public void setManagedProfileMaximumTimeOff(ComponentName who, long timeoutMs) {
+ public void setManagedProfileMaximumTimeOff(ComponentName who, long timeoutMillis) {
final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
@@ -15837,10 +15847,10 @@
// DO shouldn't be able to use this method.
enforceProfileOwnerOfOrganizationOwnedDevice(admin);
enforceHandlesCheckPolicyComplianceIntent(userId, admin.info.getPackageName());
- if (admin.mProfileMaximumTimeOff == timeoutMs) {
+ if (admin.mProfileMaximumTimeOffMillis == timeoutMillis) {
return;
}
- admin.mProfileMaximumTimeOff = timeoutMs;
+ admin.mProfileMaximumTimeOffMillis = timeoutMillis;
saveSettingsLocked(userId);
}
@@ -15850,7 +15860,7 @@
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_MANAGED_PROFILE_MAXIMUM_TIME_OFF)
.setAdmin(who)
- .setTimePeriod(timeoutMs)
+ .setTimePeriod(timeoutMillis)
.write();
}
@@ -15874,7 +15884,7 @@
false /* parent */);
// DO shouldn't be able to use this method.
enforceProfileOwnerOfOrganizationOwnedDevice(admin);
- return admin.mProfileMaximumTimeOff;
+ return admin.mProfileMaximumTimeOffMillis;
}
}
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 2426e8f..cccd0133 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -28,6 +28,7 @@
#include <androidfw/ZipFileRO.h>
#include <androidfw/ZipUtils.h>
#include <binder/BinderService.h>
+#include <binder/Nullable.h>
#include <binder/ParcelFileDescriptor.h>
#include <binder/Status.h>
#include <sys/stat.h>
@@ -917,19 +918,23 @@
}
bool IncrementalService::startLoading(StorageId storage) const {
- const auto ifs = getIfs(storage);
- if (!ifs) {
- return false;
- }
- std::unique_lock l(ifs->lock);
- if (ifs->dataLoaderStatus != IDataLoaderStatusListener::DATA_LOADER_CREATED) {
- if (ifs->dataLoaderReady.wait_for(l, Seconds(5)) == std::cv_status::timeout) {
- LOG(ERROR) << "Timeout waiting for data loader to be ready";
+ {
+ std::unique_lock l(mLock);
+ const auto& ifs = getIfsLocked(storage);
+ if (!ifs) {
return false;
}
+ if (ifs->dataLoaderStatus != IDataLoaderStatusListener::DATA_LOADER_CREATED) {
+ ifs->dataLoaderStartRequested = true;
+ return true;
+ }
}
+ return startDataLoader(storage);
+}
+
+bool IncrementalService::startDataLoader(MountId mountId) const {
sp<IDataLoader> dataloader;
- auto status = mDataLoaderManager->getDataLoader(ifs->mountId, &dataloader);
+ auto status = mDataLoaderManager->getDataLoader(mountId, &dataloader);
if (!status.isOk()) {
return false;
}
@@ -1065,15 +1070,9 @@
}
return true; // eventually...
}
- if (base::GetBoolProperty("incremental.skip_loader", false)) {
- LOG(INFO) << "Skipped data loader because of incremental.skip_loader property";
- std::unique_lock l(ifs.lock);
- ifs.savedDataLoaderParams.reset();
- return true;
- }
std::unique_lock l(ifs.lock);
- if (ifs.dataLoaderStatus == IDataLoaderStatusListener::DATA_LOADER_CREATED) {
+ if (ifs.dataLoaderStatus != -1) {
LOG(INFO) << "Skipped data loader preparation because it already exists";
return true;
}
@@ -1085,7 +1084,7 @@
return false;
}
FileSystemControlParcel fsControlParcel;
- fsControlParcel.incremental = std::make_unique<IncrementalFileSystemControlParcel>();
+ fsControlParcel.incremental = aidl::make_nullable<IncrementalFileSystemControlParcel>();
fsControlParcel.incremental->cmd.reset(base::unique_fd(::dup(ifs.control.cmd)));
fsControlParcel.incremental->pendingReads.reset(
base::unique_fd(::dup(ifs.control.pendingReads)));
@@ -1226,30 +1225,42 @@
externalListener->onStatusChanged(mountId, newStatus);
}
- 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;
- return binder::Status::ok();
+ bool startRequested = false;
+ {
+ 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;
+ return binder::Status::ok();
+ }
+ ifs->dataLoaderStatus = newStatus;
+
+ if (newStatus == IDataLoaderStatusListener::DATA_LOADER_DESTROYED) {
+ ifs->dataLoaderStatus = IDataLoaderStatusListener::DATA_LOADER_STOPPED;
+ incrementalService.deleteStorageLocked(*ifs, std::move(l));
+ return binder::Status::ok();
+ }
+
+ startRequested = ifs->dataLoaderStartRequested;
}
- ifs->dataLoaderStatus = newStatus;
+
switch (newStatus) {
case IDataLoaderStatusListener::DATA_LOADER_NO_CONNECTION: {
// TODO(b/150411019): handle data loader connection loss
break;
}
case IDataLoaderStatusListener::DATA_LOADER_CONNECTION_OK: {
- ifs->dataLoaderStatus = IDataLoaderStatusListener::DATA_LOADER_STARTED;
+ // TODO(b/150411019): handle data loader connection loss
break;
}
case IDataLoaderStatusListener::DATA_LOADER_CREATED: {
- ifs->dataLoaderReady.notify_one();
+ if (startRequested) {
+ incrementalService.startDataLoader(mountId);
+ }
break;
}
case IDataLoaderStatusListener::DATA_LOADER_DESTROYED: {
- ifs->dataLoaderStatus = IDataLoaderStatusListener::DATA_LOADER_STOPPED;
- incrementalService.deleteStorageLocked(*ifs, std::move(l));
break;
}
case IDataLoaderStatusListener::DATA_LOADER_STARTED: {
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index 8ff441b..406b32e 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -170,7 +170,7 @@
std::optional<DataLoaderParamsParcel> savedDataLoaderParams;
std::atomic<int> nextStorageDirNo{0};
std::atomic<int> dataLoaderStatus = -1;
- std::condition_variable dataLoaderReady;
+ bool dataLoaderStartRequested = false;
TimePoint connectionLostTime = TimePoint();
const IncrementalService& incrementalService;
@@ -208,6 +208,8 @@
bool prepareDataLoader(IncFsMount& ifs, DataLoaderParamsParcel* params = nullptr,
const DataLoaderStatusListener* externalListener = nullptr);
+ bool startDataLoader(MountId mountId) const;
+
BindPathMap::const_iterator findStorageLocked(std::string_view path) const;
StorageId findStorageId(std::string_view path) const;
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 95f4e83..c45ee7b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ApplicationExitInfoTest.java
@@ -55,6 +55,7 @@
import android.text.TextUtils;
import android.util.Pair;
+import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.appop.AppOpsService;
import com.android.server.wm.ActivityTaskManagerService;
@@ -125,6 +126,8 @@
mAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper());
mAms.mAtmInternal = spy(mAms.mActivityTaskManager.getAtmInternal());
mAms.mPackageManagerInt = mPackageManagerInt;
+ doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent();
+ LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt);
}
@After
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index fc2ae40..053a798 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -75,8 +75,10 @@
import android.app.IApplicationThread;
import android.app.IServiceConnection;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ServiceInfo;
import android.os.Build;
import android.os.IBinder;
@@ -87,6 +89,7 @@
import android.util.ArraySet;
import android.util.SparseArray;
+import com.android.server.LocalServices;
import com.android.server.wm.ActivityServiceConnectionsHolder;
import com.android.server.wm.ActivityTaskManagerService;
import com.android.server.wm.WindowProcessController;
@@ -127,6 +130,7 @@
private static final String MOCKAPP5_PROCESSNAME = "test #5";
private static final String MOCKAPP5_PACKAGENAME = "com.android.test.test5";
private static Context sContext;
+ private static PackageManagerInternal sPackageManagerInternal;
private static ActivityManagerService sService;
@BeforeClass
@@ -134,13 +138,21 @@
sContext = getInstrumentation().getTargetContext();
System.setProperty("dexmaker.share_classloader", "true");
+ sPackageManagerInternal = mock(PackageManagerInternal.class);
+ doReturn(new ComponentName("", "")).when(sPackageManagerInternal)
+ .getSystemUiServiceComponent();
+ LocalServices.addService(PackageManagerInternal.class, sPackageManagerInternal);
+
sService = mock(ActivityManagerService.class);
sService.mActivityTaskManager = new ActivityTaskManagerService(sContext);
sService.mActivityTaskManager.initialize(null, null, sContext.getMainLooper());
+ sService.mPackageManagerInt = sPackageManagerInternal;
sService.mAtmInternal = spy(sService.mActivityTaskManager.getAtmInternal());
sService.mConstants = new ActivityManagerConstants(sContext, sService,
sContext.getMainThreadHandler());
+ setFieldValue(ActivityManagerService.class, sService, "mContext",
+ sContext);
ProcessList pr = new ProcessList();
pr.init(sService, new ActiveUids(sService, false), null);
setFieldValue(ActivityManagerService.class, sService, "mProcessList",
@@ -972,7 +984,7 @@
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
doReturn(null).when(sService).getTopAppLocked();
- assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, VISIBLE_APP_ADJ,
+ assertProcStates(app, PROCESS_STATE_BOUND_TOP, VISIBLE_APP_ADJ,
SCHED_GROUP_DEFAULT);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index 959dc05..de6f55b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -147,7 +147,7 @@
AndroidPackage mockMyPkg = mock(AndroidPackage.class);
when(mockMyPkg.isPrivileged()).thenReturn(false);
when(mockMyPkg.getUid()).thenReturn(mMyUid);
- when(mockMyPkg.getFeatures()).thenReturn(Collections.emptyList());
+ when(mockMyPkg.getAttributions()).thenReturn(Collections.emptyList());
when(mockPackageManagerInternal.getPackage(sMyPackageName)).thenReturn(mockMyPkg);
doReturn(mockPackageManagerInternal).when(
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
index eb2dd64..2944643 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
@@ -267,6 +267,49 @@
}
@Test
+ public void testEnableTargetSdkChangesForPackage() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addEnabledChangeWithId(1L)
+ .addDisabledChangeWithId(2L)
+ .addTargetSdkChangeWithId(3, 3L)
+ .addTargetSdkChangeWithId(4, 4L)
+ .build();
+ ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
+ .withPackageName("foo.bar")
+ .withTargetSdk(2)
+ .build();
+
+ assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isFalse();
+ assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse();
+
+ assertThat(compatConfig.enableTargetSdkChangesForPackage("foo.bar", 3)).isEqualTo(1);
+ assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isTrue();
+ assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse();
+ }
+
+ @Test
+ public void testDisableTargetSdkChangesForPackage() throws Exception {
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addEnabledChangeWithId(1L)
+ .addDisabledChangeWithId(2L)
+ .addTargetSdkChangeWithId(3, 3L)
+ .addTargetSdkChangeWithId(4, 4L)
+ .build();
+ ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
+ .withPackageName("foo.bar")
+ .withTargetSdk(2)
+ .build();
+
+ assertThat(compatConfig.enableTargetSdkChangesForPackage("foo.bar", 3)).isEqualTo(1);
+ assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isTrue();
+ assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse();
+
+ assertThat(compatConfig.disableTargetSdkChangesForPackage("foo.bar", 3)).isEqualTo(1);
+ assertThat(compatConfig.isChangeEnabled(3, applicationInfo)).isFalse();
+ assertThat(compatConfig.isChangeEnabled(4, applicationInfo)).isFalse();
+ }
+
+ @Test
public void testLookupChangeId() throws Exception {
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
.addEnabledChangeWithIdAndName(1234L, "MY_CHANGE")
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 2a6a24e..7571f09 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -3872,79 +3872,80 @@
Settings.System.SCREEN_BRIGHTNESS, "0", DpmMockContext.CALLER_USER_HANDLE);
}
- public void testSetAutoTimeModifiesSetting() throws Exception {
+ public void testSetAutoTimeEnabledModifiesSetting() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
- dpm.setAutoTime(admin1, true);
+ dpm.setAutoTimeEnabled(admin1, true);
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 1);
- dpm.setAutoTime(admin1, false);
+ dpm.setAutoTimeEnabled(admin1, false);
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
}
- public void testSetAutoTimeWithPOOnUser0() throws Exception {
+ public void testSetAutoTimeEnabledWithPOOnUser0() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupProfileOwnerOnUser0();
- dpm.setAutoTime(admin1, true);
+ dpm.setAutoTimeEnabled(admin1, true);
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 1);
- dpm.setAutoTime(admin1, false);
+ dpm.setAutoTimeEnabled(admin1, false);
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
}
- public void testSetAutoTimeFailWithPONotOnUser0() throws Exception {
+ public void testSetAutoTimeEnabledFailWithPONotOnUser0() throws Exception {
setupProfileOwner();
- assertExpectException(SecurityException.class, null, () -> dpm.setAutoTime(admin1, false));
+ assertExpectException(SecurityException.class, null,
+ () -> dpm.setAutoTimeEnabled(admin1, false));
verify(getServices().settings, never()).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
}
- public void testSetAutoTimeWithPOOfOrganizationOwnedDevice() throws Exception {
+ public void testSetAutoTimeEnabledWithPOOfOrganizationOwnedDevice() throws Exception {
setupProfileOwner();
configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE);
- dpm.setAutoTime(admin1, true);
+ dpm.setAutoTimeEnabled(admin1, true);
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 1);
- dpm.setAutoTime(admin1, false);
+ dpm.setAutoTimeEnabled(admin1, false);
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
}
- public void testSetAutoTimeZoneModifiesSetting() throws Exception {
+ public void testSetAutoTimeZoneEnabledModifiesSetting() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
- dpm.setAutoTimeZone(admin1, true);
+ dpm.setAutoTimeZoneEnabled(admin1, true);
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 1);
- dpm.setAutoTimeZone(admin1, false);
+ dpm.setAutoTimeZoneEnabled(admin1, false);
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 0);
}
- public void testSetAutoTimeZoneWithPOOnUser0() throws Exception {
+ public void testSetAutoTimeZoneEnabledWithPOOnUser0() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupProfileOwnerOnUser0();
- dpm.setAutoTimeZone(admin1, true);
+ dpm.setAutoTimeZoneEnabled(admin1, true);
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 1);
- dpm.setAutoTimeZone(admin1, false);
+ dpm.setAutoTimeZoneEnabled(admin1, false);
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 0);
}
- public void testSetAutoTimeZoneFailWithPONotOnUser0() throws Exception {
+ public void testSetAutoTimeZoneEnabledFailWithPONotOnUser0() throws Exception {
setupProfileOwner();
assertExpectException(SecurityException.class, null,
- () -> dpm.setAutoTimeZone(admin1, false));
+ () -> dpm.setAutoTimeZoneEnabled(admin1, false));
verify(getServices().settings, never()).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE,
0);
}
- public void testSetAutoTimeZoneWithPOOfOrganizationOwnedDevice() throws Exception {
+ public void testSetAutoTimeZoneEnabledWithPOOfOrganizationOwnedDevice() throws Exception {
setupProfileOwner();
configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE);
- dpm.setAutoTimeZone(admin1, true);
+ dpm.setAutoTimeZoneEnabled(admin1, true);
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 1);
- dpm.setAutoTimeZone(admin1, false);
+ dpm.setAutoTimeZoneEnabled(admin1, false);
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 0);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 1c267a0..6eec649 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -203,10 +203,11 @@
final IApplicationThread caller = mock(IApplicationThread.class);
final WindowProcessListener listener = mock(WindowProcessListener.class);
+ final ApplicationInfo ai = new ApplicationInfo();
+ ai.packageName = "com.android.test.package";
final WindowProcessController wpc =
containsConditions(preconditions, PRECONDITION_NO_CALLER_APP)
- ? null : new WindowProcessController(
- service, mock(ApplicationInfo.class), null, 0, -1, null, listener);
+ ? null : new WindowProcessController(service, ai, null, 0, -1, null, listener);
doReturn(wpc).when(service).getProcessController(anyObject());
final Intent intent = new Intent();
@@ -345,6 +346,7 @@
doReturn(false).when(mMockPackageManager).isInstantAppInstallerComponent(any());
doReturn(null).when(mMockPackageManager).resolveIntent(any(), any(), anyInt(), anyInt(),
anyInt(), anyBoolean(), anyInt());
+ doReturn(new ComponentName("", "")).when(mMockPackageManager).getSystemUiServiceComponent();
// Never review permissions
doReturn(false).when(mMockPackageManager).isPermissionsReviewRequired(any(), anyInt());
@@ -656,6 +658,7 @@
final WindowProcessListener listener = mock(WindowProcessListener.class);
final ApplicationInfo ai = new ApplicationInfo();
ai.uid = callingUid;
+ ai.packageName = "com.android.test.package";
final WindowProcessController callerApp =
new WindowProcessController(mService, ai, null, callingUid, -1, null, listener);
callerApp.setHasForegroundActivities(hasForegroundActivities);
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 5cf1fbb..a380ece 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
@@ -69,7 +71,7 @@
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
statusBar.setControllableInsetProvider(getController().getSourceProvider(ITYPE_STATUS_BAR));
- assertNotNull(getController().getInsetsForDispatch(app).getSource(ITYPE_STATUS_BAR));
+ assertNotNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_STATUS_BAR));
}
@Test
@@ -101,6 +103,34 @@
}
@Test
+ public void testStripForDispatch_pip() {
+ 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_PINNED);
+
+ assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_STATUS_BAR));
+ assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_NAVIGATION_BAR));
+ }
+
+ @Test
+ public void testStripForDispatch_freeform() {
+ 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_FREEFORM);
+
+ 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/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index ac4c228..12d89de 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -131,6 +131,7 @@
LocalServices.addService(PackageManagerInternal.class, mMockPmi);
when(mMockPmi.getPackageList(any())).thenReturn(new PackageList(
Collections.singletonList(TEST_COMPONENT.getPackageName()), /* observer */ null));
+ when(mMockPmi.getSystemUiServiceComponent()).thenReturn(new ComponentName("", ""));
mTarget.onSystemReady();
final ArgumentCaptor<PackageManagerInternal.PackageListObserver> observerCaptor =
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 55d12db..560d03f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -40,6 +40,7 @@
import android.app.AppOpsManager;
import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IntentFilter;
@@ -213,6 +214,9 @@
anyString(), anyInt());
doReturn(null).when(packageManagerInternal).getDefaultHomeActivity(anyInt());
+ ComponentName systemServiceComponent = new ComponentName("android.test.system.service", "");
+ doReturn(systemServiceComponent).when(packageManagerInternal).getSystemUiServiceComponent();
+
// PowerManagerInternal
final PowerManagerInternal pmi = mock(PowerManagerInternal.class);
final PowerSaveState state = new PowerSaveState.Builder().build();
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 53a3682..19ed7a9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -213,6 +213,16 @@
}
@Test
+ public void testRegisterTaskOrganizerWithExistingTasks() throws RemoteException {
+ final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
+ final Task task = createTaskInStack(stack, 0 /* userId */);
+ stack.setWindowingMode(WINDOWING_MODE_PINNED);
+
+ final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
+ verify(organizer, times(1)).taskAppeared(any());
+ }
+
+ @Test
public void testTaskTransaction() {
removeGlobalMinSizeRestriction();
final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
@@ -241,6 +251,32 @@
}
@Test
+ public void testSetWindowingMode() {
+ final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
+ final WindowContainerTransaction t = new WindowContainerTransaction();
+
+ t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN);
+ mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
+
+ assertEquals(WINDOWING_MODE_FULLSCREEN, stack.getWindowingMode());
+ }
+
+ @Test
+ public void testSetActivityWindowingMode() {
+ final ActivityRecord record = makePipableActivity();
+ final ActivityStack stack = record.getStack();
+ final WindowContainerTransaction t = new WindowContainerTransaction();
+
+ t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_PINNED);
+ t.setActivityWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN);
+ mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
+
+ assertEquals(WINDOWING_MODE_FULLSCREEN, record.getWindowingMode());
+ assertEquals(WINDOWING_MODE_PINNED, stack.getWindowingMode());
+ }
+
+ @Test
public void testContainerChanges() {
removeGlobalMinSizeRestriction();
final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index e1475a4..91c3c27 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -77,7 +77,8 @@
}
@Override
- public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, boolean sync)
+ public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, float zoom,
+ boolean sync)
throws RemoteException {
}
@@ -85,7 +86,6 @@
public void dispatchWallpaperCommand(String action, int x, int y, int z, Bundle extras,
boolean sync) throws RemoteException {
}
-
@Override
public void dispatchDragEvent(DragEvent event) throws RemoteException {
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index aa66524..900f014 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -17,19 +17,29 @@
package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.IBinder;
+import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.view.DisplayInfo;
import android.view.Gravity;
@@ -139,4 +149,124 @@
assertEquals(Configuration.ORIENTATION_LANDSCAPE, dc.getConfiguration().orientation);
assertEquals(portraitFrame, wallpaperWindow.getFrameLw());
}
+
+ @Test
+ public void testWallpaperZoom() throws RemoteException {
+ final DisplayContent dc = mWm.mRoot.getDefaultDisplay();
+ final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
+ mock(IBinder.class), true, dc, true /* ownerCanManageAppTokens */);
+ final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken,
+ "wallpaperWindow");
+ wallpaperWindow.getAttrs().privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
+
+ final WindowState homeWindow = createWallpaperTargetWindow(dc);
+
+ spyOn(dc.mWallpaperController);
+ doReturn(true).when(dc.mWallpaperController).isWallpaperVisible();
+
+ dc.mWallpaperController.adjustWallpaperWindows();
+
+ spyOn(wallpaperWindow.mClient);
+
+ float zoom = .5f;
+ dc.mWallpaperController.setWallpaperZoomOut(homeWindow, zoom);
+ assertEquals(zoom, wallpaperWindow.mWallpaperZoomOut, .01f);
+ verify(wallpaperWindow.mClient).dispatchWallpaperOffsets(anyFloat(), anyFloat(), anyFloat(),
+ anyFloat(), eq(zoom), anyBoolean());
+ }
+
+ @Test
+ public void testWallpaperZoom_shouldNotScaleWallpaper() throws RemoteException {
+ final DisplayContent dc = mWm.mRoot.getDefaultDisplay();
+ final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
+ mock(IBinder.class), true, dc, true /* ownerCanManageAppTokens */);
+ final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken,
+ "wallpaperWindow");
+ wallpaperWindow.getAttrs().privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
+
+ final WindowState homeWindow = createWallpaperTargetWindow(dc);
+
+ spyOn(dc.mWallpaperController);
+ doReturn(true).when(dc.mWallpaperController).isWallpaperVisible();
+
+ dc.mWallpaperController.adjustWallpaperWindows();
+
+ spyOn(wallpaperWindow.mClient);
+
+ float newZoom = .5f;
+ wallpaperWindow.mShouldScaleWallpaper = false;
+ // Set zoom, and make sure the window animator scale didn't actually change, but the zoom
+ // value did, and we do dispatch the zoom to the wallpaper service
+ dc.mWallpaperController.setWallpaperZoomOut(homeWindow, newZoom);
+ assertEquals(newZoom, wallpaperWindow.mWallpaperZoomOut, .01f);
+ assertEquals(1f, wallpaperWindow.mWinAnimator.mWallpaperScale, .01f);
+ verify(wallpaperWindow.mClient).dispatchWallpaperOffsets(anyFloat(), anyFloat(), anyFloat(),
+ anyFloat(), eq(newZoom), anyBoolean());
+ }
+
+ @Test
+ public void testWallpaperZoom_multipleCallers() {
+ final DisplayContent dc = mWm.mRoot.getDefaultDisplay();
+ final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
+ mock(IBinder.class), true, dc,
+ true /* ownerCanManageAppTokens */);
+ final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken,
+ "wallpaperWindow");
+ wallpaperWindow.getAttrs().privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
+
+
+ spyOn(dc.mWallpaperController);
+ doReturn(true).when(dc.mWallpaperController).isWallpaperVisible();
+
+ final WindowState homeWindow = createWallpaperTargetWindow(dc);
+
+ WindowState otherWindow = createWindow(null /* parent */, TYPE_APPLICATION, dc,
+ "otherWindow");
+
+ dc.mWallpaperController.adjustWallpaperWindows();
+
+ spyOn(wallpaperWindow.mClient);
+
+ // Set zoom from 2 windows
+ float homeWindowInitialZoom = .5f;
+ float otherWindowInitialZoom = .7f;
+ dc.mWallpaperController.setWallpaperZoomOut(homeWindow, homeWindowInitialZoom);
+ dc.mWallpaperController.setWallpaperZoomOut(otherWindow, otherWindowInitialZoom);
+ // Make sure the largest one wins
+ assertEquals(otherWindowInitialZoom, wallpaperWindow.mWallpaperZoomOut, .01f);
+
+ // Change zoom to a larger zoom from homeWindow
+ float homeWindowZoom2 = .8f;
+ dc.mWallpaperController.setWallpaperZoomOut(homeWindow, homeWindowZoom2);
+ // New zoom should be current
+ assertEquals(homeWindowZoom2, wallpaperWindow.mWallpaperZoomOut, .01f);
+
+ // Set homeWindow zoom to a lower zoom, but keep the one from otherWindow
+ dc.mWallpaperController.setWallpaperZoomOut(homeWindow, homeWindowInitialZoom);
+
+ // Zoom from otherWindow should be the current.
+ assertEquals(otherWindowInitialZoom, wallpaperWindow.mWallpaperZoomOut, .01f);
+ }
+
+
+ private WindowState createWallpaperTargetWindow(DisplayContent dc) {
+ final ActivityRecord homeActivity = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
+ .setStack(dc.getRootHomeTask())
+ .setCreateTask(true)
+ .build();
+ homeActivity.setVisibility(true);
+
+ WindowState appWindow = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
+ homeActivity, "wallpaperTargetWindow");
+ appWindow.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
+ appWindow.mHasSurface = true;
+ spyOn(appWindow);
+ doReturn(true).when(appWindow).isDrawFinishedLw();
+
+ homeActivity.addWindow(appWindow);
+ return appWindow;
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index 34e487b..07a6179 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -29,6 +29,7 @@
import static org.mockito.Mockito.when;
import android.app.IApplicationThread;
+import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.platform.test.annotations.Presubmit;
@@ -55,8 +56,11 @@
@Before
public void setUp() {
mMockListener = mock(WindowProcessListener.class);
+
+ ApplicationInfo info = mock(ApplicationInfo.class);
+ info.packageName = "test.package.name";
mWpc = new WindowProcessController(
- mService, mock(ApplicationInfo.class), null, 0, -1, null, mMockListener);
+ mService, info, null, 0, -1, null, mMockListener);
mWpc.setThread(mock(IApplicationThread.class));
}
@@ -176,6 +180,26 @@
assertEquals(mWpc.getLastReportedConfiguration(), newConfig);
}
+ @Test
+ public void testActivityNotOverridingSystemUiProcessConfig() {
+ final ComponentName systemUiServiceComponent = mService.getSysUiServiceComponentLocked();
+ ApplicationInfo applicationInfo = mock(ApplicationInfo.class);
+ applicationInfo.packageName = systemUiServiceComponent.getPackageName();
+
+ WindowProcessController wpc = new WindowProcessController(
+ mService, applicationInfo, null, 0, -1, null, mMockListener);
+ wpc.setThread(mock(IApplicationThread.class));
+
+ final ActivityRecord activity = new ActivityBuilder(mService)
+ .setCreateTask(true)
+ .setUseProcess(wpc)
+ .build();
+
+ wpc.addActivityIfNeeded(activity);
+ // System UI owned processes should not be registered for activity config changes.
+ assertFalse(wpc.registeredForActivityConfigChanges());
+ }
+
private TestDisplayContent createTestDisplayContentInContainer() {
return new TestDisplayContent.Builder(mService, 1000, 1500).build();
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
index af81ab6..be0987d 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
@@ -257,6 +257,9 @@
int userHandle) {
SQLiteDatabase db = getReadableDatabase();
Cursor c = db.rawQuery(selectQuery, null);
+ if (DBG) {
+ Slog.w(TAG, "querying database: " + selectQuery);
+ }
try {
if (c.moveToFirst()) {
@@ -334,7 +337,10 @@
return model;
} while (c.moveToNext());
}
- Slog.w(TAG, "No SoundModel available for the given keyphrase");
+
+ if (DBG) {
+ Slog.w(TAG, "No SoundModel available for the given keyphrase");
+ }
} finally {
c.close();
db.close();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 0b24dd2..0eba07b 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -41,6 +41,7 @@
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
import android.hardware.soundtrigger.KeyphraseMetadata;
import android.hardware.soundtrigger.ModelParams;
import android.hardware.soundtrigger.SoundTrigger;
@@ -223,6 +224,7 @@
class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub {
VoiceInteractionManagerServiceImpl mImpl;
+ KeyphraseEnrollmentInfo mEnrollmentApplicationInfo;
private boolean mSafeMode;
private int mCurUser;
@@ -447,6 +449,15 @@
}
}
+ private void getOrCreateEnrollmentApplicationInfo() {
+ synchronized (this) {
+ if (mEnrollmentApplicationInfo == null) {
+ mEnrollmentApplicationInfo = new KeyphraseEnrollmentInfo(
+ mContext.getPackageManager());
+ }
+ }
+ }
+
private void setCurrentUserLocked(@UserIdInt int userHandle) {
mCurUser = userHandle;
final UserInfo userInfo = mUserManagerInternal.getUserInfo(mCurUser);
@@ -1380,12 +1391,17 @@
pw.println(" mCurUserUnlocked: " + mCurUserUnlocked);
pw.println(" mCurUserSupported: " + mCurUserSupported);
dumpSupportedUsers(pw, " ");
+ if (mEnrollmentApplicationInfo == null) {
+ pw.println(" (No enrollment application info)");
+ } else {
+ pw.println(" " + mEnrollmentApplicationInfo.toString());
+ }
mDbHelper.dump(pw);
if (mImpl == null) {
pw.println(" (No active implementation)");
- return;
+ } else {
+ mImpl.dumpLocked(fd, pw, args);
}
- mImpl.dumpLocked(fd, pw, args);
}
mSoundTriggerInternal.dump(fd, pw, args);
}
@@ -1438,8 +1454,9 @@
}
private boolean isCallerTrustedEnrollmentApplication() {
- return mImpl.mEnrollmentApplicationInfo.isUidSupportedEnrollmentApplication(
- Binder.getCallingUid());
+ getOrCreateEnrollmentApplicationInfo();
+ return mEnrollmentApplicationInfo.isUidSupportedEnrollmentApplication(
+ Binder.getCallingUid());
}
private void setImplLocked(VoiceInteractionManagerServiceImpl impl) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index b813f87..a62b03c 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -36,7 +36,6 @@
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
-import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -79,7 +78,6 @@
final IActivityManager mAm;
final IActivityTaskManager mAtm;
final VoiceInteractionServiceInfo mInfo;
- final KeyphraseEnrollmentInfo mEnrollmentApplicationInfo;
final ComponentName mSessionComponentName;
final IWindowManager mIWindowManager;
boolean mBound = false;
@@ -135,7 +133,6 @@
mComponent = service;
mAm = ActivityManager.getService();
mAtm = ActivityTaskManager.getService();
- mEnrollmentApplicationInfo = new KeyphraseEnrollmentInfo(context.getPackageManager());
VoiceInteractionServiceInfo info;
try {
info = new VoiceInteractionServiceInfo(context.getPackageManager(), service, mUser);
@@ -406,7 +403,6 @@
pw.println(" Active session:");
mActiveSession.dump(" ", pw);
}
- pw.println(" " + mEnrollmentApplicationInfo.toString());
}
void startLocked() {
diff --git a/telecomm/java/android/telecom/CallRedirectionService.java b/telecomm/java/android/telecom/CallRedirectionService.java
index 36c6377..c832f53 100644
--- a/telecomm/java/android/telecom/CallRedirectionService.java
+++ b/telecomm/java/android/telecom/CallRedirectionService.java
@@ -38,16 +38,14 @@
*
* <p>
* Below is an example manifest registration for a {@code CallRedirectionService}.
- * <pre>
* {@code
* <service android:name="your.package.YourCallRedirectionServiceImplementation"
- * android:permission="android.permission.BIND_REDIRECTION_SERVICE">
+ * android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE">
* <intent-filter>
* <action android:name="android.telecom.CallRedirectionService"/>
* </intent-filter>
* </service>
* }
- * </pre>
*/
public abstract class CallRedirectionService extends Service {
/**
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index 0093843..bebbbd0 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -80,17 +80,20 @@
* Reason code (returned via {@link #getReason()}) which indicates that a call could not be
* completed because the cellular radio is off or out of service, the device is connected to
* a wifi network, but the user has not enabled wifi calling.
+ * @hide
*/
public static final String REASON_WIFI_ON_BUT_WFC_OFF = "REASON_WIFI_ON_BUT_WFC_OFF";
/**
* Reason code (returned via {@link #getReason()}), which indicates that the video telephony
* call was disconnected because IMS access is blocked.
+ * @hide
*/
public static final String REASON_IMS_ACCESS_BLOCKED = "REASON_IMS_ACCESS_BLOCKED";
/**
* Reason code, which indicates that the conference call is simulating single party conference.
+ * @hide
*/
public static final String REASON_EMULATING_SINGLE_CALL = "EMULATING_SINGLE_CALL";
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 4e6e1a5..768c8ee 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -53,7 +53,6 @@
* {@link android.telecom.ConnectionService}.
* @hide
*/
- @SystemApi
public static final String EXTRA_SORT_ORDER =
"android.telecom.extra.SORT_ORDER";
@@ -89,7 +88,6 @@
* rather than cellular calls.
* @hide
*/
- @SystemApi
public static final String EXTRA_ALWAYS_USE_VOIP_AUDIO_MODE =
"android.telecom.extra.ALWAYS_USE_VOIP_AUDIO_MODE";
@@ -114,7 +112,6 @@
*
* @hide
*/
- @SystemApi
public static final String EXTRA_SUPPORTS_VIDEO_CALLING_FALLBACK =
"android.telecom.extra.SUPPORTS_VIDEO_CALLING_FALLBACK";
@@ -163,7 +160,6 @@
* in progress.
* @hide
*/
- @SystemApi
public static final String EXTRA_PLAY_CALL_RECORDING_TONE =
"android.telecom.extra.PLAY_CALL_RECORDING_TONE";
@@ -258,7 +254,6 @@
* See {@link #getCapabilities}
* @hide
*/
- @SystemApi
public static final int CAPABILITY_EMERGENCY_CALLS_ONLY = 0x80;
/**
@@ -282,7 +277,6 @@
* convert all outgoing video calls to emergency numbers to audio-only.
* @hide
*/
- @SystemApi
public static final int CAPABILITY_EMERGENCY_VIDEO_CALLING = 0x200;
/**
@@ -340,7 +334,6 @@
*
* @hide
*/
- @SystemApi
public static final int CAPABILITY_EMERGENCY_PREFERRED = 0x2000;
/**
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 7f4fcc0..1792256 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -318,13 +318,13 @@
* the remote handle of the new call.
* @hide
*/
- @SystemApi
public static final String EXTRA_UNKNOWN_CALL_HANDLE =
"android.telecom.extra.UNKNOWN_CALL_HANDLE";
/**
* Optional extra for incoming and outgoing calls containing a long which specifies the time the
* call was created. This value is in milliseconds since boot.
+ * @hide
*/
public static final String EXTRA_CALL_CREATED_TIME_MILLIS =
"android.telecom.extra.CALL_CREATED_TIME_MILLIS";
@@ -388,7 +388,6 @@
* </ul>
* @hide
*/
- @SystemApi
public static final String EXTRA_CALL_TECHNOLOGY_TYPE =
"android.telecom.extra.CALL_TECHNOLOGY_TYPE";
@@ -731,7 +730,6 @@
* @see #EXTRA_CURRENT_TTY_MODE
* @hide
*/
- @SystemApi
public static final String ACTION_CURRENT_TTY_MODE_CHANGED =
"android.telecom.action.CURRENT_TTY_MODE_CHANGED";
@@ -746,7 +744,6 @@
* </ul>
* @hide
*/
- @SystemApi
public static final String EXTRA_CURRENT_TTY_MODE =
"android.telecom.extra.CURRENT_TTY_MODE";
@@ -757,7 +754,6 @@
* @see #EXTRA_TTY_PREFERRED_MODE
* @hide
*/
- @SystemApi
public static final String ACTION_TTY_PREFERRED_MODE_CHANGED =
"android.telecom.action.TTY_PREFERRED_MODE_CHANGED";
@@ -768,7 +764,6 @@
*
* @hide
*/
- @SystemApi
public static final String EXTRA_TTY_PREFERRED_MODE =
"android.telecom.extra.TTY_PREFERRED_MODE";
@@ -846,7 +841,6 @@
*
* @hide
*/
- @SystemApi
public static final String EXTRA_CALL_SOURCE = "android.telecom.extra.CALL_SOURCE";
/**
@@ -943,8 +937,8 @@
*/
public TelecomManager(Context context, ITelecomService telecomServiceImpl) {
Context appContext = context.getApplicationContext();
- if (appContext != null && Objects.equals(context.getFeatureId(),
- appContext.getFeatureId())) {
+ if (appContext != null && Objects.equals(context.getAttributionTag(),
+ appContext.getAttributionTag())) {
mContext = appContext;
} else {
mContext = context;
@@ -978,7 +972,7 @@
try {
if (isServiceConnected()) {
return getTelecomService().getDefaultOutgoingPhoneAccount(uriScheme,
- mContext.getOpPackageName(), mContext.getFeatureId());
+ mContext.getOpPackageName(), mContext.getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getDefaultOutgoingPhoneAccount", e);
@@ -1176,7 +1170,7 @@
try {
if (isServiceConnected()) {
return getTelecomService().getSelfManagedPhoneAccounts(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getSelfManagedPhoneAccounts()", e);
@@ -1202,7 +1196,7 @@
try {
if (isServiceConnected()) {
return getTelecomService().getCallCapablePhoneAccounts(includeDisabledAccounts,
- mContext.getOpPackageName(), mContext.getFeatureId());
+ mContext.getOpPackageName(), mContext.getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getCallCapablePhoneAccounts(" +
@@ -1506,7 +1500,7 @@
try {
if (isServiceConnected()) {
return getTelecomService().isVoiceMailNumber(accountHandle, number,
- mContext.getOpPackageName(), mContext.getFeatureId());
+ mContext.getOpPackageName(), mContext.getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling ITelecomService#isVoiceMailNumber.", e);
@@ -1528,7 +1522,7 @@
try {
if (isServiceConnected()) {
return getTelecomService().getVoiceMailNumber(accountHandle,
- mContext.getOpPackageName(), mContext.getFeatureId());
+ mContext.getOpPackageName(), mContext.getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling ITelecomService#hasVoiceMailNumber.", e);
@@ -1549,7 +1543,7 @@
try {
if (isServiceConnected()) {
return getTelecomService().getLine1Number(accountHandle,
- mContext.getOpPackageName(), mContext.getFeatureId());
+ mContext.getOpPackageName(), mContext.getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling ITelecomService#getLine1Number.", e);
@@ -1571,7 +1565,7 @@
try {
if (isServiceConnected()) {
return getTelecomService().isInCall(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling isInCall().", e);
@@ -1597,7 +1591,7 @@
try {
if (isServiceConnected()) {
return getTelecomService().isInManagedCall(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling isInManagedCall().", e);
@@ -1778,7 +1772,7 @@
try {
if (isServiceConnected()) {
return getTelecomService().isTtySupported(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException attempting to get TTY supported state.", e);
@@ -1803,7 +1797,7 @@
try {
if (isServiceConnected()) {
return getTelecomService().getCurrentTtyMode(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException attempting to get the current TTY mode.", e);
@@ -2033,7 +2027,7 @@
if (service != null) {
try {
service.showInCallScreen(showDialpad, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#showCallScreen", e);
}
@@ -2096,7 +2090,7 @@
}
try {
service.placeCall(address, extras == null ? new Bundle() : extras,
- mContext.getOpPackageName(), mContext.getFeatureId());
+ mContext.getOpPackageName(), mContext.getAttributionTag());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#placeCall", e);
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index c20748b..e2112a5 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2382,17 +2382,16 @@
* <p> If a measure is not set, signal criteria reporting from modem will not be triggered and
* not be used for calculating signal level. If multiple measures are set bit, the parameter
* whose value is smallest is used to indicate the signal level.
+ * <UL>
+ * <LI>RSRP = 1 << 0</LI>
+ * <LI>RSRQ = 1 << 1</LI>
+ * <LI>RSSNR = 1 << 2</LI>
+ * </UL>
+ * <p> The value of this key must be bitwise OR of {@link CellSignalStrengthLte#USE_RSRP},
+ * {@link CellSignalStrengthLte#USE_RSRQ}, {@link CellSignalStrengthLte#USE_RSSNR}.
*
- * RSRP = 1 << 0,
- * RSRQ = 1 << 1,
- * RSSNR = 1 << 2,
- *
- * The value of this key must be bitwise OR of {@link CellSignalStrengthLte#USE_RSRP},
- * {@link CellSignalStrengthLte#USE_RSRQ}, {@link CellSignalStrengthLte#USE_RSSNR}.
- *
- * For example, if both RSRP and RSRQ are used, the value of key is 3 (1 << 0 | 1 << 1).
- * If the key is invalid or not configured, a default value (RSRP = 1 << 0)
- * will apply.
+ * <p> For example, if both RSRP and RSRQ are used, the value of key is 3 (1 << 0 | 1 << 1).
+ * If the key is invalid or not configured, a default value (RSRP = 1 << 0) will apply.
*
* @hide
*/
@@ -2401,16 +2400,18 @@
/**
* List of 4 customized 5G SS reference signal received power (SSRSRP) thresholds.
- *
+ * <p>
* Reference: 3GPP TS 38.215
- *
+ * <p>
* 4 threshold integers must be within the boundaries [-140 dB, -44 dB], and the levels are:
- * "NONE: [-140, threshold1]"
- * "POOR: (threshold1, threshold2]"
- * "MODERATE: (threshold2, threshold3]"
- * "GOOD: (threshold3, threshold4]"
- * "EXCELLENT: (threshold4, -44]"
- *
+ * <UL>
+ * <LI>"NONE: [-140, threshold1]"</LI>
+ * <LI>"POOR: (threshold1, threshold2]"</LI>
+ * <LI>"MODERATE: (threshold2, threshold3]"</LI>
+ * <LI>"GOOD: (threshold3, threshold4]"</LI>
+ * <LI>"EXCELLENT: (threshold4, -44]"</LI>
+ * </UL>
+ * <p>
* This key is considered invalid if the format is violated. If the key is invalid or
* not configured, a default value set will apply.
*/
@@ -2419,16 +2420,18 @@
/**
* List of 4 customized 5G SS reference signal received quality (SSRSRQ) thresholds.
- *
+ * <p>
* Reference: 3GPP TS 38.215
- *
+ * <p>
* 4 threshold integers must be within the boundaries [-20 dB, -3 dB], and the levels are:
- * "NONE: [-20, threshold1]"
- * "POOR: (threshold1, threshold2]"
- * "MODERATE: (threshold2, threshold3]"
- * "GOOD: (threshold3, threshold4]"
- * "EXCELLENT: (threshold4, -3]"
- *
+ * <UL>
+ * <LI>"NONE: [-20, threshold1]"</LI>
+ * <LI>"POOR: (threshold1, threshold2]"</LI>
+ * <LI>"MODERATE: (threshold2, threshold3]"</LI>
+ * <LI>"GOOD: (threshold3, threshold4]"</LI>
+ * <LI>"EXCELLENT: (threshold4, -3]"</LI>
+ * </UL>
+ * <p>
* This key is considered invalid if the format is violated. If the key is invalid or
* not configured, a default value set will apply.
*/
@@ -2437,17 +2440,19 @@
/**
* List of 4 customized 5G SS signal-to-noise and interference ratio (SSSINR) thresholds.
- *
+ * <p>
* Reference: 3GPP TS 38.215,
* 3GPP TS 38.133 10.1.16.1
- *
+ * <p>
* 4 threshold integers must be within the boundaries [-23 dB, 40 dB], and the levels are:
- * "NONE: [-23, threshold1]"
- * "POOR: (threshold1, threshold2]"
- * "MODERATE: (threshold2, threshold3]"
- * "GOOD: (threshold3, threshold4]"
- * "EXCELLENT: (threshold4, 40]"
- *
+ * <UL>
+ * <LI>"NONE: [-23, threshold1]"</LI>
+ * <LI>"POOR: (threshold1, threshold2]"</LI>
+ * <LI>"MODERATE: (threshold2, threshold3]"</LI>
+ * <LI>"GOOD: (threshold3, threshold4]"</LI>
+ * <LI>"EXCELLENT: (threshold4, 40]"</LI>
+ * </UL>
+ * <p>
* This key is considered invalid if the format is violated. If the key is invalid or
* not configured, a default value set will apply.
*/
@@ -2462,19 +2467,19 @@
* <p> If a measure is not set, signal criteria reporting from modem will not be triggered and
* not be used for calculating signal level. If multiple measures are set bit, the parameter
* whose value is smallest is used to indicate the signal level.
- *
- * SSRSRP = 1 << 0,
- * SSRSRQ = 1 << 1,
- * SSSINR = 1 << 2,
- *
+ * <UL>
+ * <LI>SSRSRP = 1 << 0</LI>
+ * <LI>SSRSRQ = 1 << 1</LI>
+ * <LI>SSSINR = 1 << 2</LI>
+ * </UL>
* The value of this key must be bitwise OR of {@link CellSignalStrengthNr#USE_SSRSRP},
* {@link CellSignalStrengthNr#USE_SSRSRQ}, {@link CellSignalStrengthNr#USE_SSSINR}.
*
- * For example, if both SSRSRP and SSSINR are used, the value of key is 5 (1 << 0 | 1 << 2).
+ * <p> For example, if both SSRSRP and SSSINR are used, the value of key is 5 (1 << 0 | 1 << 2).
* If the key is invalid or not configured, a default value (SSRSRP = 1 << 0) will apply.
*
- * Reference: 3GPP TS 38.215,
- * 3GPP TS 38.133 10.1.16.1
+ * <p> Reference: 3GPP TS 38.215,
+ * 3GPP TS 38.133 10.1.16.1
*
* @hide
*/
@@ -4157,7 +4162,7 @@
return null;
}
return loader.getConfigForSubIdWithFeature(subId, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException ex) {
Rlog.e(TAG, "Error getting config for subId " + subId + ": "
+ ex.toString());
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 45cba51..dd20d06 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -580,7 +580,6 @@
*
* @hide
*/
- @SystemApi
public @RegState int getDataRegistrationState() {
return getDataRegState();
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 8ac9023b..01a40f5 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1144,7 +1144,7 @@
ISub iSub = TelephonyManager.getSubscriptionService();
if (iSub != null) {
subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException ex) {
// ignore it
@@ -1178,7 +1178,7 @@
ISub iSub = TelephonyManager.getSubscriptionService();
if (iSub != null) {
result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException ex) {
// ignore it
@@ -1212,7 +1212,7 @@
ISub iSub = TelephonyManager.getSubscriptionService();
if (iSub != null) {
result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIndex,
- mContext.getOpPackageName(), mContext.getFeatureId());
+ mContext.getOpPackageName(), mContext.getAttributionTag());
}
} catch (RemoteException ex) {
// ignore it
@@ -1236,7 +1236,7 @@
ISub iSub = TelephonyManager.getSubscriptionService();
if (iSub != null) {
result = iSub.getAllSubInfoList(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException ex) {
// ignore it
@@ -1300,8 +1300,13 @@
* both active and hidden SubscriptionInfos.
*
*/
- public @Nullable List<SubscriptionInfo> getActiveAndHiddenSubscriptionInfoList() {
- return getActiveSubscriptionInfoList(/* userVisibleonly */false);
+ public @NonNull List<SubscriptionInfo> getCompleteActiveSubscriptionInfoList() {
+ List<SubscriptionInfo> completeList = getActiveSubscriptionInfoList(
+ /* userVisibleonly */false);
+ if (completeList == null) {
+ completeList = new ArrayList<>();
+ }
+ return completeList;
}
/**
@@ -1317,7 +1322,7 @@
ISub iSub = TelephonyManager.getSubscriptionService();
if (iSub != null) {
activeList = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException ex) {
// ignore it
@@ -1368,7 +1373,7 @@
ISub iSub = TelephonyManager.getSubscriptionService();
if (iSub != null) {
result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException ex) {
// ignore it
@@ -1486,7 +1491,7 @@
ISub iSub = TelephonyManager.getSubscriptionService();
if (iSub != null) {
result = iSub.getAllSubInfoCount(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException ex) {
// ignore it
@@ -1515,7 +1520,7 @@
ISub iSub = TelephonyManager.getSubscriptionService();
if (iSub != null) {
result = iSub.getActiveSubInfoCount(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException ex) {
// ignore it
@@ -2270,7 +2275,7 @@
ISub iSub = TelephonyManager.getSubscriptionService();
if (iSub != null) {
resultValue = iSub.getSubscriptionProperty(subId, propKey,
- context.getOpPackageName(), context.getFeatureId());
+ context.getOpPackageName(), context.getAttributionTag());
}
} catch (RemoteException ex) {
// ignore it
@@ -2434,7 +2439,7 @@
ISub iSub = TelephonyManager.getSubscriptionService();
if (iSub != null) {
return iSub.isActiveSubId(subId, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException ex) {
}
@@ -2697,13 +2702,14 @@
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public @NonNull List<SubscriptionInfo> getOpportunisticSubscriptions() {
String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>";
- String contextFeature = mContext != null ? mContext.getFeatureId() : null;
+ String contextAttributionTag = mContext != null ? mContext.getAttributionTag() : null;
List<SubscriptionInfo> subInfoList = null;
try {
ISub iSub = TelephonyManager.getSubscriptionService();
if (iSub != null) {
- subInfoList = iSub.getOpportunisticSubscriptions(contextPkg, contextFeature);
+ subInfoList = iSub.getOpportunisticSubscriptions(contextPkg,
+ contextAttributionTag);
}
} catch (RemoteException ex) {
// ignore it
@@ -2942,7 +2948,7 @@
public @NonNull List<SubscriptionInfo> getSubscriptionsInGroup(@NonNull ParcelUuid groupUuid) {
Preconditions.checkNotNull(groupUuid, "groupUuid can't be null");
String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>";
- String contextFeature = mContext != null ? mContext.getFeatureId() : null;
+ String contextAttributionTag = mContext != null ? mContext.getAttributionTag() : null;
if (VDBG) {
logd("[getSubscriptionsInGroup]+ groupUuid:" + groupUuid);
}
@@ -2951,7 +2957,8 @@
try {
ISub iSub = TelephonyManager.getSubscriptionService();
if (iSub != null) {
- result = iSub.getSubscriptionsInGroup(groupUuid, contextPkg, contextFeature);
+ result = iSub.getSubscriptionsInGroup(groupUuid, contextPkg,
+ contextAttributionTag);
} else {
if (!isSystemProcess()) {
throw new IllegalStateException("telephony service is null.");
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 631eaac..08251da 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -345,10 +345,10 @@
mSubId = subId;
Context appContext = context.getApplicationContext();
if (appContext != null) {
- if (Objects.equals(context.getFeatureId(), appContext.getFeatureId())) {
+ if (Objects.equals(context.getAttributionTag(), appContext.getAttributionTag())) {
mContext = appContext;
} else {
- mContext = appContext.createFeatureContext(context.getFeatureId());
+ mContext = appContext.createAttributionContext(context.getAttributionTag());
}
} else {
mContext = context;
@@ -393,12 +393,12 @@
}
}
- private String getFeatureId() {
+ private String getAttributionTag() {
// For legacy reasons the TelephonyManager has API for getting
// a static instance with no context set preventing us from
- // getting the feature Id.
+ // getting the attribution tag.
if (mContext != null) {
- return mContext.getFeatureId();
+ return mContext.getAttributionTag();
}
return null;
}
@@ -1896,7 +1896,7 @@
try {
return telephony.getDeviceSoftwareVersionForSlot(slotIndex, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1938,7 +1938,7 @@
if (telephony == null)
return null;
return telephony.getDeviceIdWithFeature(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1983,7 +1983,7 @@
if (info == null)
return null;
return info.getDeviceIdForPhone(slotIndex, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -2041,7 +2041,7 @@
if (telephony == null) return null;
try {
- return telephony.getImeiForSlot(slotIndex, getOpPackageName(), getFeatureId());
+ return telephony.getImeiForSlot(slotIndex, getOpPackageName(), getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -2135,7 +2135,8 @@
if (telephony == null) return null;
try {
- String meid = telephony.getMeidForSlot(slotIndex, getOpPackageName(), getFeatureId());
+ String meid = telephony.getMeidForSlot(slotIndex, getOpPackageName(),
+ getAttributionTag());
if (TextUtils.isEmpty(meid)) {
Log.d(TAG, "getMeid: return null because MEID is not available");
return null;
@@ -2237,7 +2238,7 @@
if (info == null)
return null;
String nai = info.getNaiForSubscriber(subId, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Rlog.v(TAG, "Nai = " + nai);
}
@@ -2271,7 +2272,7 @@
}
CellIdentity cellIdentity = telephony.getCellLocation(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
CellLocation cl = cellIdentity.asCellLocation();
if (cl == null || cl.isEmpty()) {
Rlog.d(TAG, "getCellLocation returning null because CellLocation is empty or"
@@ -2355,7 +2356,7 @@
if (telephony == null)
return null;
return telephony.getNeighboringCellInfo(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -2371,7 +2372,12 @@
public static final int PHONE_TYPE_CDMA = PhoneConstants.PHONE_TYPE_CDMA;
/** Phone is via SIP. */
public static final int PHONE_TYPE_SIP = PhoneConstants.PHONE_TYPE_SIP;
- /** Phone is via IMS. */
+
+ /**
+ * Phone is via IMS.
+ *
+ * @hide
+ */
public static final int PHONE_TYPE_IMS = PhoneConstants.PHONE_TYPE_IMS;
/**
@@ -2379,7 +2385,6 @@
*
* @hide
*/
- @SystemApi
public static final int PHONE_TYPE_THIRD_PARTY = PhoneConstants.PHONE_TYPE_THIRD_PARTY;
/**
@@ -2957,7 +2962,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.getNetworkTypeForSubscriber(subId, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -3022,7 +3027,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.getDataNetworkTypeForSubscriber(subId, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -3059,7 +3064,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.getVoiceNetworkTypeForSubscriber(subId, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -3763,29 +3768,6 @@
}
/**
- * Returns the ISO-3166 country code equivalent for the SIM provider's country code
- * of the default subscription
- * <p>
- * The ISO-3166 country code is provided in lowercase 2 character format.
- * @return the lowercase 2 character ISO-3166 country code, or empty string is not available.
- * <p>
- * Note: This API is introduced to unblock mainlining work as the following APIs in
- * Linkify.java invokes getSimCountryIso() without a context. TODO(Bug 144576376): remove
- * this API once the following APIs are redesigned to access telephonymanager with a context.
- *
- * {@link Linkify#addLinks(@NonNull Spannable text, @LinkifyMask int mask)}
- * {@link Linkify#addLinks(@NonNull Spannable text, @LinkifyMask int mask,
- @Nullable Function<String, URLSpan> urlSpanFactory)}
- *
- * @hide
- */
- @SystemApi
- @NonNull
- public static String getDefaultSimCountryIso() {
- return getSimCountryIso(SubscriptionManager.getDefaultSubscriptionId());
- }
-
- /**
* Returns the ISO country code equivalent for the SIM provider's country code.
*
* @param subId for which SimCountryIso is returned
@@ -3868,7 +3850,7 @@
if (info == null)
return null;
return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -3912,7 +3894,7 @@
if (telephony == null)
return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
return telephony.getLteOnCdmaModeForSubscriber(subId, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} catch (RemoteException ex) {
// Assume no ICC card if remote exception which shouldn't happen
return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
@@ -4141,7 +4123,7 @@
if (info == null)
return null;
return info.getSubscriberIdForSubscriber(subId, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4309,7 +4291,7 @@
if (info == null)
return null;
return info.getGroupIdLevel1ForSubscriber(getSubId(), mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4333,7 +4315,7 @@
if (info == null)
return null;
return info.getGroupIdLevel1ForSubscriber(subId, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4384,7 +4366,7 @@
ITelephony telephony = getITelephony();
if (telephony != null)
number = telephony.getLine1NumberForDisplay(subId, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -4396,7 +4378,7 @@
if (info == null)
return null;
return info.getLine1NumberForSubscriber(subId, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4475,7 +4457,7 @@
ITelephony telephony = getITelephony();
if (telephony != null)
alphaTag = telephony.getLine1AlphaTagForDisplay(subId,
- getOpPackageName(), getFeatureId());
+ getOpPackageName(), getAttributionTag());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -4487,7 +4469,7 @@
if (info == null)
return null;
return info.getLine1AlphaTagForSubscriber(subId, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4517,7 +4499,7 @@
ITelephony telephony = getITelephony();
if (telephony != null)
return telephony.getMergedSubscriberIds(getSubId(), getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -4574,7 +4556,7 @@
IPhoneSubInfo info = getSubscriberInfoService();
if (info == null)
return null;
- return info.getMsisdnForSubscriber(subId, getOpPackageName(), getFeatureId());
+ return info.getMsisdnForSubscriber(subId, getOpPackageName(), getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4609,7 +4591,7 @@
if (info == null)
return null;
return info.getVoiceMailNumberForSubscriber(subId, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -4734,7 +4716,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.getVisualVoicemailPackageName(mContext.getOpPackageName(),
- getFeatureId(), getSubId());
+ getAttributionTag(), getSubId());
}
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
@@ -5171,7 +5153,7 @@
if (telephony == null)
return 0;
return telephony.getVoiceMessageCountForSubscriber(subId, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} catch (RemoteException ex) {
return 0;
} catch (NullPointerException ex) {
@@ -5208,7 +5190,7 @@
if (info == null)
return null;
return info.getVoiceMailAlphaTagForSubscriber(subId, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -5591,7 +5573,7 @@
(TelephonyRegistryManager)
mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
if (telephonyRegistry != null) {
- telephonyRegistry.listenForSubscriber(mSubId, getOpPackageName(), getFeatureId(),
+ telephonyRegistry.listenForSubscriber(mSubId, getOpPackageName(), getAttributionTag(),
listener, events, notifyNow);
} else {
Rlog.w(TAG, "telephony registry not ready.");
@@ -5624,7 +5606,7 @@
if (telephony == null)
return -1;
return telephony.getCdmaEriIconIndexForSubscriber(subId, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} catch (RemoteException ex) {
// the phone process is restarting.
return -1;
@@ -5648,7 +5630,7 @@
if (telephony == null)
return -1;
return telephony.getCdmaEriIconModeForSubscriber(subId, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} catch (RemoteException ex) {
// the phone process is restarting.
return -1;
@@ -5680,7 +5662,7 @@
if (telephony == null)
return null;
return telephony.getCdmaEriTextForSubscriber(subId, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} catch (RemoteException ex) {
// the phone process is restarting.
return null;
@@ -5772,7 +5754,7 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getAllCellInfo(getOpPackageName(), getFeatureId());
+ return telephony.getAllCellInfo(getOpPackageName(), getAttributionTag());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -5872,7 +5854,7 @@
Binder.restoreCallingIdentity(identity);
}
}
- }, getOpPackageName(), getFeatureId());
+ }, getOpPackageName(), getAttributionTag());
} catch (RemoteException ex) {
}
}
@@ -5923,7 +5905,7 @@
Binder.restoreCallingIdentity(identity);
}
}
- }, getOpPackageName(), getFeatureId(), workSource);
+ }, getOpPackageName(), getAttributionTag(), workSource);
} catch (RemoteException ex) {
}
}
@@ -7209,7 +7191,7 @@
if (telephony == null)
return null;
return telephony.getForbiddenPlmns(subId, appType, mContext.getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -7243,7 +7225,7 @@
ITelephony telephony = getITelephony();
if (telephony == null) return -1;
return telephony.setForbiddenPlmns(
- getSubId(), APPTYPE_USIM, fplmns, getOpPackageName(), getFeatureId());
+ getSubId(), APPTYPE_USIM, fplmns, getOpPackageName(), getAttributionTag());
} catch (RemoteException ex) {
Rlog.e(TAG, "setForbiddenPlmns RemoteException: " + ex.getMessage());
} catch (NullPointerException ex) {
@@ -7264,7 +7246,7 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return new String[0];
- return telephony.getPcscfAddress(apnType, getOpPackageName(), getFeatureId());
+ return telephony.getPcscfAddress(apnType, getOpPackageName(), getAttributionTag());
} catch (RemoteException e) {
return new String[0];
}
@@ -7837,7 +7819,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.getCellNetworkScanResults(getSubId(), getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
}
} catch (RemoteException ex) {
Rlog.e(TAG, "getAvailableNetworks RemoteException", ex);
@@ -7892,7 +7874,7 @@
}
}
return mTelephonyScanManager.requestNetworkScan(getSubId(), request, executor, callback,
- getOpPackageName(), getFeatureId());
+ getOpPackageName(), getAttributionTag());
}
/**
@@ -8646,7 +8628,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.isRadioOnWithFeature(getOpPackageName(), getFeatureId());
+ return telephony.isRadioOnWithFeature(getOpPackageName(), getAttributionTag());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isRadioOn", e);
}
@@ -8940,7 +8922,10 @@
}
/**
- * Shut down all the live radios over all the slot index.
+ * Shut down all the live radios over all the slot indexes.
+ *
+ * <p>To know when the radio has completed powering off, use
+ * {@link PhoneStateListener#LISTEN_SERVICE_STATE LISTEN_SERVICE_STATE}.
*
* @hide
*/
@@ -8953,7 +8938,8 @@
telephony.shutdownMobileRadios();
}
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#shutdownMobileRadios", e);
+ Log.e(TAG, "Error calling ITelephony#shutdownAllRadios", e);
+ e.rethrowAsRuntimeException();
}
}
@@ -8972,7 +8958,8 @@
return telephony.needMobileRadioShutdown();
}
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#needMobileRadioShutdown", e);
+ Log.e(TAG, "Error calling ITelephony#isAnyRadioPoweredOn", e);
+ e.rethrowAsRuntimeException();
}
return false;
}
@@ -9015,7 +9002,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.getRadioPowerState(getSlotIndex(), mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
@@ -9406,7 +9393,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.isVideoCallingEnabled(getOpPackageName(), getFeatureId());
+ return telephony.isVideoCallingEnabled(getOpPackageName(), getAttributionTag());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isVideoCallingEnabled", e);
}
@@ -9423,7 +9410,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.canChangeDtmfToneLength(mSubId, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#canChangeDtmfToneLength", e);
@@ -9442,7 +9429,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.isWorldPhone(mSubId, getOpPackageName(), getFeatureId());
+ return telephony.isWorldPhone(mSubId, getOpPackageName(), getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isWorldPhone", e);
@@ -10170,7 +10157,8 @@
ITelephony service = getITelephony();
if (service != null) {
retval = service.getSubIdForPhoneAccountHandle(
- phoneAccountHandle, mContext.getOpPackageName(), mContext.getFeatureId());
+ phoneAccountHandle, mContext.getOpPackageName(),
+ mContext.getAttributionTag());
}
} catch (RemoteException ex) {
Log.e(TAG, "getSubscriptionId RemoteException", ex);
@@ -10311,7 +10299,7 @@
ITelephony service = getITelephony();
if (service != null) {
return service.getServiceStateForSubscriber(subId, getOpPackageName(),
- getFeatureId());
+ getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getServiceStateForSubscriber", e);
@@ -11032,7 +11020,8 @@
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.getClientRequestStats(getOpPackageName(), getFeatureId(), subId);
+ return service.getClientRequestStats(getOpPackageName(), getAttributionTag(),
+ subId);
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getClientRequestStats", e);
@@ -11143,21 +11132,21 @@
}
/**
- * Checks whether cellular data connection is enabled in the device.
+ * Checks whether cellular data connection is allowed in the device.
*
- * Whether cellular data connection is enabled, meaning upon request whether will try to setup
- * metered data connection considering all factors below:
- * 1) User turned on data setting {@link #isDataEnabled}.
- * 2) Carrier allows data to be on.
- * 3) Network policy.
- * And possibly others.
- *
- * @return {@code true} if the overall data connection is capable; {@code false} if not.
+ * <p>Whether cellular data connection is allowed considers all factors below:
+ * <UL>
+ * <LI>User turned on data setting {@link #isDataEnabled}.</LI>
+ * <LI>Carrier allows data to be on.</LI>
+ * <LI>Network policy.</LI>
+ * <LI>And possibly others.</LI>
+ * </UL>
+ * @return {@code true} if the overall data connection is allowed; {@code false} if not.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public boolean isDataConnectionEnabled() {
+ public boolean isDataConnectionAllowed() {
boolean retVal = false;
try {
int subId = getSubId(SubscriptionManager.getDefaultDataSubscriptionId());
@@ -11165,8 +11154,9 @@
if (telephony != null)
retVal = telephony.isDataEnabled(subId);
} catch (RemoteException e) {
- Log.e(TAG, "Error isDataConnectionEnabled", e);
+ Log.e(TAG, "Error isDataConnectionAllowed", e);
} catch (NullPointerException e) {
+ return false;
}
return retVal;
}
@@ -11317,7 +11307,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.getNumberOfModemsWithSimultaneousDataConnections(
- getSubId(), getOpPackageName(), getFeatureId());
+ getSubId(), getOpPackageName(), getAttributionTag());
}
} catch (RemoteException ex) {
// This could happen if binder process crashes.
@@ -11747,7 +11737,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.getEmergencyNumberList(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} else {
throw new IllegalStateException("telephony service is null.");
}
@@ -11802,7 +11792,7 @@
ITelephony telephony = getITelephony();
if (telephony != null) {
emergencyNumberList = telephony.getEmergencyNumberList(
- mContext.getOpPackageName(), mContext.getFeatureId());
+ mContext.getOpPackageName(), mContext.getAttributionTag());
if (emergencyNumberList != null) {
for (Integer subscriptionId : emergencyNumberList.keySet()) {
List<EmergencyNumber> numberList = emergencyNumberList.get(subscriptionId);
@@ -11895,7 +11885,7 @@
}
/**
- * A test API to return the emergency number db version.
+ * Returns the emergency number database version.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
@@ -11904,6 +11894,7 @@
*/
@TestApi
@SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public int getEmergencyNumberDbVersion() {
try {
ITelephony telephony = getITelephony();
@@ -12110,13 +12101,13 @@
})
public int getPreferredOpportunisticDataSubscription() {
String packageName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
- String featureId = mContext != null ? mContext.getFeatureId() : null;
+ String attributionTag = mContext != null ? mContext.getAttributionTag() : null;
int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
try {
IOns iOpportunisticNetworkService = getIOns();
if (iOpportunisticNetworkService != null) {
subId = iOpportunisticNetworkService.getPreferredDataSubscriptionId(
- packageName, featureId);
+ packageName, attributionTag);
}
} catch (RemoteException ex) {
Rlog.e(TAG, "getPreferredDataSubscriptionId RemoteException", ex);
@@ -12233,18 +12224,20 @@
/**
* It indicates whether modem is enabled or not per slot.
- * It's the corresponding status of {@link #enableModemForSlot}.
+ * It's the corresponding status of TelephonyManager.enableModemForSlot.
*
+ * <p>Requires Permission:
+ * READ_PRIVILEGED_PHONE_STATE or
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* @param slotIndex which slot it's checking.
- * @hide
*/
- @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
public boolean isModemEnabledForSlot(int slotIndex) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.isModemEnabledForSlot(slotIndex, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
}
} catch (RemoteException ex) {
Log.e(TAG, "enableModem RemoteException", ex);
@@ -12349,7 +12342,7 @@
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.isMultiSimSupported(getOpPackageName(), getFeatureId());
+ return service.isMultiSimSupported(getOpPackageName(), getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "isMultiSimSupported RemoteException", e);
@@ -12401,7 +12394,7 @@
ITelephony service = getITelephony();
if (service != null) {
return service.doesSwitchMultiSimConfigTriggerReboot(getSubId(),
- getOpPackageName(), getFeatureId());
+ getOpPackageName(), getAttributionTag());
}
} catch (RemoteException e) {
Log.e(TAG, "doesSwitchMultiSimConfigTriggerReboot RemoteException", e);
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 3341fa7..4b5303f 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -294,8 +294,15 @@
throw new IllegalArgumentException("Must include a non-null Executor.");
}
c.setExecutor(executor);
+
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new ImsException("Could not find Telephony Service.",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
try {
- getITelephony().registerImsRegistrationCallback(mSubId, c.getBinder());
+ iTelephony.registerImsRegistrationCallback(mSubId, c.getBinder());
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -331,8 +338,15 @@
throw new IllegalArgumentException("Must include a non-null Executor.");
}
c.setExecutor(executor);
+
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new ImsException("Could not find Telephony Service.",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
try {
- getITelephony().registerImsRegistrationCallback(mSubId, c.getBinder());
+ iTelephony.registerImsRegistrationCallback(mSubId, c.getBinder());
} catch (ServiceSpecificException e) {
throw new ImsException(e.getMessage(), e.errorCode);
} catch (RemoteException | IllegalStateException e) {
@@ -361,8 +375,14 @@
if (c == null) {
throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
}
+
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- getITelephony().unregisterImsRegistrationCallback(mSubId, c.getBinder());
+ iTelephony.unregisterImsRegistrationCallback(mSubId, c.getBinder());
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
@@ -387,8 +407,14 @@
if (c == null) {
throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
}
+
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- getITelephony().unregisterImsRegistrationCallback(mSubId, c.getBinder());
+ iTelephony.unregisterImsRegistrationCallback(mSubId, c.getBinder());
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
@@ -409,8 +435,14 @@
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
}
+
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- getITelephony().getImsMmTelRegistrationState(mSubId, new IIntegerConsumer.Stub() {
+ iTelephony.getImsMmTelRegistrationState(mSubId, new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
executor.execute(() -> stateCallback.accept(result));
@@ -443,8 +475,14 @@
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
}
+
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- getITelephony().getImsMmTelRegistrationTransportType(mSubId,
+ iTelephony.getImsMmTelRegistrationTransportType(mSubId,
new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
@@ -506,8 +544,15 @@
throw new IllegalArgumentException("Must include a non-null Executor.");
}
c.setExecutor(executor);
+
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new ImsException("Could not find Telephony Service.",
+ ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
+ }
+
try {
- getITelephony().registerMmTelCapabilityCallback(mSubId, c.getBinder());
+ iTelephony.registerMmTelCapabilityCallback(mSubId, c.getBinder());
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -553,8 +598,14 @@
if (c == null) {
throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
}
+
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- getITelephony().unregisterMmTelCapabilityCallback(mSubId, c.getBinder());
+ iTelephony.unregisterMmTelCapabilityCallback(mSubId, c.getBinder());
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
@@ -599,8 +650,13 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public boolean isAdvancedCallingSettingEnabled() {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- return getITelephony().isAdvancedCallingSettingEnabled(mSubId);
+ return iTelephony.isAdvancedCallingSettingEnabled(mSubId);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -640,8 +696,13 @@
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi @TestApi
public void setAdvancedCallingSettingEnabled(boolean isEnabled) {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- getITelephony().setAdvancedCallingSettingEnabled(mSubId, isEnabled);
+ iTelephony.setAdvancedCallingSettingEnabled(mSubId, isEnabled);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -680,8 +741,13 @@
@SystemApi @TestApi
public boolean isCapable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- return getITelephony().isCapable(mSubId, capability, imsRegTech);
+ return iTelephony.isCapable(mSubId, capability, imsRegTech);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
@@ -709,8 +775,13 @@
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isAvailable(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- return getITelephony().isAvailable(mSubId, capability, imsRegTech);
+ return iTelephony.isAvailable(mSubId, capability, imsRegTech);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
@@ -744,6 +815,13 @@
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
}
+
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new ImsException("Could not find Telephony Service.",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
try {
getITelephony().isMmTelCapabilitySupported(mSubId, new IIntegerConsumer.Stub() {
@Override
@@ -788,8 +866,13 @@
android.Manifest.permission.READ_PRECISE_PHONE_STATE})
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
public boolean isVtSettingEnabled() {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- return getITelephony().isVtSettingEnabled(mSubId);
+ return iTelephony.isVtSettingEnabled(mSubId);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -813,8 +896,13 @@
@SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVtSettingEnabled(boolean isEnabled) {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- getITelephony().setVtSettingEnabled(mSubId, isEnabled);
+ iTelephony.setVtSettingEnabled(mSubId, isEnabled);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -853,8 +941,13 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public boolean isVoWiFiSettingEnabled() {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- return getITelephony().isVoWiFiSettingEnabled(mSubId);
+ return iTelephony.isVoWiFiSettingEnabled(mSubId);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -879,8 +972,13 @@
@SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiSettingEnabled(boolean isEnabled) {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- getITelephony().setVoWiFiSettingEnabled(mSubId, isEnabled);
+ iTelephony.setVoWiFiSettingEnabled(mSubId, isEnabled);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -921,8 +1019,13 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public boolean isVoWiFiRoamingSettingEnabled() {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- return getITelephony().isVoWiFiRoamingSettingEnabled(mSubId);
+ return iTelephony.isVoWiFiRoamingSettingEnabled(mSubId);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -948,8 +1051,13 @@
@SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiRoamingSettingEnabled(boolean isEnabled) {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- getITelephony().setVoWiFiRoamingSettingEnabled(mSubId, isEnabled);
+ iTelephony.setVoWiFiRoamingSettingEnabled(mSubId, isEnabled);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -980,8 +1088,13 @@
@SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiNonPersistent(boolean isCapable, int mode) {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- getITelephony().setVoWiFiNonPersistent(mSubId, isCapable, mode);
+ iTelephony.setVoWiFiNonPersistent(mSubId, isCapable, mode);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -1025,8 +1138,13 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public @WiFiCallingMode int getVoWiFiModeSetting() {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- return getITelephony().getVoWiFiModeSetting(mSubId);
+ return iTelephony.getVoWiFiModeSetting(mSubId);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -1054,8 +1172,13 @@
@SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiModeSetting(@WiFiCallingMode int mode) {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- getITelephony().setVoWiFiModeSetting(mSubId, mode);
+ iTelephony.setVoWiFiModeSetting(mSubId, mode);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -1085,8 +1208,13 @@
@SystemApi @TestApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @WiFiCallingMode int getVoWiFiRoamingModeSetting() {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- return getITelephony().getVoWiFiRoamingModeSetting(mSubId);
+ return iTelephony.getVoWiFiRoamingModeSetting(mSubId);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -1116,8 +1244,13 @@
@SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setVoWiFiRoamingModeSetting(@WiFiCallingMode int mode) {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- getITelephony().setVoWiFiRoamingModeSetting(mSubId, mode);
+ iTelephony.setVoWiFiRoamingModeSetting(mSubId, mode);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -1145,8 +1278,13 @@
@SystemApi @TestApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setRttCapabilitySetting(boolean isEnabled) {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- getITelephony().setRttCapabilitySetting(mSubId, isEnabled);
+ iTelephony.setRttCapabilitySetting(mSubId, isEnabled);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -1186,8 +1324,13 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
android.Manifest.permission.READ_PRECISE_PHONE_STATE})
public boolean isTtyOverVolteEnabled() {
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+
try {
- return getITelephony().isTtyOverVolteEnabled(mSubId);
+ return iTelephony.isTtyOverVolteEnabled(mSubId);
} catch (ServiceSpecificException e) {
if (e.errorCode == ImsException.CODE_ERROR_INVALID_SUBSCRIPTION) {
// Rethrow as runtime error to keep API compatible.
@@ -1223,8 +1366,15 @@
if (callback == null) {
throw new IllegalArgumentException("Must include a non-null Consumer.");
}
+
+ ITelephony iTelephony = getITelephony();
+ if (iTelephony == null) {
+ throw new ImsException("Could not find Telephony Service.",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
try {
- getITelephony().getImsMmTelFeatureState(mSubId, new IIntegerConsumer.Stub() {
+ iTelephony.getImsMmTelFeatureState(mSubId, new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
executor.execute(() -> callback.accept(result));
@@ -1243,9 +1393,6 @@
.getTelephonyServiceManager()
.getTelephonyServiceRegisterer()
.get());
- if (binder == null) {
- throw new RuntimeException("Could not find Telephony Service.");
- }
return binder;
}
}
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index 30306c7..05ab6bd 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -291,7 +291,7 @@
try {
imsRcsController.requestCapabilities(mSubId, mContext.getOpPackageName(),
- mContext.getFeatureId(), contactNumbers, internalCallback);
+ mContext.getAttributionTag(), contactNumbers, internalCallback);
} catch (RemoteException e) {
Log.e(TAG, "Error calling IImsRcsController#requestCapabilities", e);
throw new ImsException("Remote IMS Service is not available",
@@ -352,7 +352,7 @@
try {
// Telephony.SimInfo#IMS_RCS_UCE_ENABLED can also be used to listen to changes to this.
return imsRcsController.isUceSettingEnabled(mSubId, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException e) {
Log.e(TAG, "Error calling IImsRcsController#isUceSettingEnabled", e);
throw new ImsException("Remote IMS Service is not available",
diff --git a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
index 5904916..c7e5a5e 100644
--- a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
@@ -322,7 +322,7 @@
mAtm.startActivityAndWait(null,
getInstrumentation().getContext().getBasePackageName(),
- getInstrumentation().getContext().getFeatureId(), mLaunchIntent,
+ getInstrumentation().getContext().getAttributionTag(), mLaunchIntent,
mimeType, null, null, 0, mLaunchIntent.getFlags(), null, null,
UserHandle.USER_CURRENT_OR_SELF);
} catch (RemoteException e) {
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 819fc02..8cc8cf4 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -1063,52 +1063,6 @@
assertThat(bootObserver2.mitigatedBootLoop()).isFalse();
}
- /**
- * 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()
@@ -1265,7 +1219,6 @@
private Consumer<String> mPassedConsumer;
private Consumer<List<PackageConfig>> mSupportedConsumer;
private Runnable mNotifySyncRunnable;
- private List<Set> mSyncRequests = new ArrayList<>();
@Override
public void setEnabled(boolean enabled) {
@@ -1285,7 +1238,6 @@
@Override
public void syncRequests(Set<String> packages) {
- mSyncRequests.add(packages);
mRequestedPackages.clear();
if (mIsEnabled) {
packages.retainAll(mSupportedPackages);
@@ -1316,10 +1268,6 @@
return Collections.emptyList();
}
}
-
- public List<Set> getSyncRequests() {
- return mSyncRequests;
- }
}
private static class TestClock implements PackageWatchdog.SystemClock {
diff --git a/tests/net/common/java/android/net/util/SocketUtilsTest.kt b/tests/net/common/java/android/net/util/SocketUtilsTest.kt
index 9c7cfb0..aaf97f3 100644
--- a/tests/net/common/java/android/net/util/SocketUtilsTest.kt
+++ b/tests/net/common/java/android/net/util/SocketUtilsTest.kt
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-package android.net.util;
+package android.net.util
+import android.os.Build
import android.system.NetlinkSocketAddress
import android.system.Os
import android.system.OsConstants.AF_INET
@@ -26,18 +27,26 @@
import android.system.PacketSocketAddress
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
private const val TEST_INDEX = 123
private const val TEST_PORT = 555
+private const val FF_BYTE = 0xff.toByte()
+
@RunWith(AndroidJUnit4::class)
@SmallTest
class SocketUtilsTest {
+ @Rule @JvmField
+ val ignoreRule = DevSdkIgnoreRule()
+
@Test
fun testMakeNetlinkSocketAddress() {
val nlAddress = SocketUtils.makeNetlinkSocketAddress(TEST_PORT, RTMGRP_NEIGH)
@@ -50,16 +59,21 @@
}
@Test
- fun testMakePacketSocketAddress() {
+ fun testMakePacketSocketAddress_Q() {
val pkAddress = SocketUtils.makePacketSocketAddress(ETH_P_ALL, TEST_INDEX)
assertTrue("Not PacketSocketAddress object", pkAddress is PacketSocketAddress)
- val ff = 0xff.toByte()
- val pkAddress2 = SocketUtils.makePacketSocketAddress(TEST_INDEX,
- byteArrayOf(ff, ff, ff, ff, ff, ff))
+ val pkAddress2 = SocketUtils.makePacketSocketAddress(TEST_INDEX, ByteArray(6) { FF_BYTE })
assertTrue("Not PacketSocketAddress object", pkAddress2 is PacketSocketAddress)
}
+ @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
+ fun testMakePacketSocketAddress() {
+ val pkAddress = SocketUtils.makePacketSocketAddress(
+ ETH_P_ALL, TEST_INDEX, ByteArray(6) { FF_BYTE })
+ assertTrue("Not PacketSocketAddress object", pkAddress is PacketSocketAddress)
+ }
+
@Test
fun testCloseSocket() {
// Expect no exception happening with null object.
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 5aa32f8..bcfce66 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -366,8 +366,12 @@
});
manifest_action["instrumentation"]["meta-data"] = meta_data_action;
+ // TODO moltmann: Remove
manifest_action["feature"];
manifest_action["feature"]["inherit-from"];
+
+ manifest_action["attribution"];
+ manifest_action["attribution"]["inherit-from"];
manifest_action["original-package"];
manifest_action["overlay"];
manifest_action["protected-broadcast"];
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java
index 2b47623..a269e17 100644
--- a/wifi/java/android/net/wifi/SoftApConfiguration.java
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.java
@@ -35,7 +35,6 @@
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import java.util.Objects;
@@ -211,7 +210,7 @@
* Delay in milliseconds before shutting down soft AP when
* there are no connected devices.
*/
- private final int mShutdownTimeoutMillis;
+ private final long mShutdownTimeoutMillis;
/**
* THe definition of security type OPEN.
@@ -247,7 +246,7 @@
private SoftApConfiguration(@Nullable String ssid, @Nullable MacAddress bssid,
@Nullable String passphrase, boolean hiddenSsid, @BandType int band, int channel,
@SecurityType int securityType, int maxNumberOfClients, boolean shutdownTimeoutEnabled,
- int shutdownTimeoutMillis, boolean clientControlByUser,
+ long shutdownTimeoutMillis, boolean clientControlByUser,
@NonNull List<MacAddress> blockedList, @NonNull List<MacAddress> allowedList) {
mSsid = ssid;
mBssid = bssid;
@@ -327,7 +326,7 @@
dest.writeInt(mSecurityType);
dest.writeInt(mMaxNumberOfClients);
dest.writeBoolean(mAutoShutdownEnabled);
- dest.writeInt(mShutdownTimeoutMillis);
+ dest.writeLong(mShutdownTimeoutMillis);
dest.writeBoolean(mClientControlByUser);
dest.writeTypedList(mBlockedClientList);
dest.writeTypedList(mAllowedClientList);
@@ -346,7 +345,7 @@
in.readString(),
in.readParcelable(MacAddress.class.getClassLoader()),
in.readString(), in.readBoolean(), in.readInt(), in.readInt(), in.readInt(),
- in.readInt(), in.readBoolean(), in.readInt(), in.readBoolean(),
+ in.readInt(), in.readBoolean(), in.readLong(), in.readBoolean(),
in.createTypedArrayList(MacAddress.CREATOR),
in.createTypedArrayList(MacAddress.CREATOR));
}
@@ -454,19 +453,19 @@
/**
* Returns the shutdown timeout in milliseconds.
* The Soft AP will shutdown when there are no devices associated to it for
- * the timeout duration. See {@link Builder#setShutdownTimeoutMillis(int)}.
+ * the timeout duration. See {@link Builder#setShutdownTimeoutMillis(long)}.
*
* @hide
*/
@SystemApi
- public int getShutdownTimeoutMillis() {
+ public long getShutdownTimeoutMillis() {
return mShutdownTimeoutMillis;
}
/**
* Returns a flag indicating whether clients need to be pre-approved by the user.
* (true: authorization required) or not (false: not required).
- * {@link Builder#enableClientControlByUser(Boolean)}.
+ * {@link Builder#setClientControlByUserEnabled(Boolean)}.
*
* @hide
*/
@@ -478,7 +477,7 @@
/**
* Returns List of clients which aren't allowed to associate to the AP.
*
- * Clients are configured using {@link Builder#setClientList(List, List)}
+ * Clients are configured using {@link Builder#setBlockedClientList(List)}
*
* @hide
*/
@@ -490,7 +489,7 @@
/**
* List of clients which are allowed to associate to the AP.
- * Clients are configured using {@link Builder#setClientList(List, List)}
+ * Clients are configured using {@link Builder#setAllowedClientList(List)}
*
* @hide
*/
@@ -575,7 +574,7 @@
private int mMaxNumberOfClients;
private int mSecurityType;
private boolean mAutoShutdownEnabled;
- private int mShutdownTimeoutMillis;
+ private long mShutdownTimeoutMillis;
private boolean mClientControlByUser;
private List<MacAddress> mBlockedClientList;
private List<MacAddress> mAllowedClientList;
@@ -627,6 +626,11 @@
*/
@NonNull
public SoftApConfiguration build() {
+ for (MacAddress client : mAllowedClientList) {
+ if (mBlockedClientList.contains(client)) {
+ throw new IllegalArgumentException("A MacAddress exist in both client list");
+ }
+ }
return new SoftApConfiguration(mSsid, mBssid, mPassphrase,
mHiddenSsid, mBand, mChannel, mSecurityType, mMaxNumberOfClients,
mAutoShutdownEnabled, mShutdownTimeoutMillis, mClientControlByUser,
@@ -835,7 +839,7 @@
* @param enable true to enable, false to disable.
* @return Builder for chaining.
*
- * @see #setShutdownTimeoutMillis(int)
+ * @see #setShutdownTimeoutMillis(long)
*/
@NonNull
public Builder setAutoShutdownEnabled(boolean enable) {
@@ -862,7 +866,7 @@
* @see #setAutoShutdownEnabled(boolean)
*/
@NonNull
- public Builder setShutdownTimeoutMillis(@IntRange(from = 0) int timeoutMillis) {
+ public Builder setShutdownTimeoutMillis(@IntRange(from = 0) long timeoutMillis) {
if (timeoutMillis < 0) {
throw new IllegalArgumentException("Invalid timeout value");
}
@@ -878,7 +882,7 @@
*
* If manual user control is enabled then clients will be accepted, rejected, or require
* a user approval based on the configuration provided by
- * {@link #setClientList(List, List)}.
+ * {@link #setBlockedClientList(List)} and {@link #setAllowedClientList(List)}.
*
* <p>
* This method requires hardware support. Hardware support can be determined using
@@ -898,26 +902,48 @@
* @return Builder for chaining.
*/
@NonNull
- public Builder enableClientControlByUser(boolean enabled) {
+ public Builder setClientControlByUserEnabled(boolean enabled) {
mClientControlByUser = enabled;
return this;
}
/**
- * This method together with {@link enableClientControlByUser(boolean)} control client
- * connections to the AP. If {@link enableClientControlByUser(false)} is configured than
+ * This method together with {@link setClientControlByUserEnabled(boolean)} control client
+ * connections to the AP. If client control by user is disabled using the above method then
* this API has no effect and clients are allowed to associate to the AP (within limit of
* max number of clients).
*
- * If {@link enableClientControlByUser(true)} is configured then this API configures
- * 2 lists:
+ * If client control by user is enabled then this API configures the list of clients
+ * which are explicitly allowed. These are auto-accepted.
+ *
+ * All other clients which attempt to associate, whose MAC addresses are on neither list,
+ * are:
* <ul>
- * <li>List of clients which are blocked. These are rejected.</li>
- * <li>List of clients which are explicitly allowed. These are auto-accepted.</li>
+ * <li>Rejected</li>
+ * <li>A callback {@link WifiManager.SoftApCallback#onBlockedClientConnecting(WifiClient)}
+ * is issued (which allows the user to add them to the allowed client list if desired).<li>
* </ul>
*
- * <p>
+ * @param allowedClientList list of clients which are allowed to associate to the AP
+ * without user pre-approval.
+ * @return Builder for chaining.
+ */
+ @NonNull
+ public Builder setAllowedClientList(@NonNull List<MacAddress> allowedClientList) {
+ mAllowedClientList = new ArrayList<>(allowedClientList);
+ return this;
+ }
+
+ /**
+ * This method together with {@link setClientControlByUserEnabled(boolean)} control client
+ * connections to the AP. If client control by user is disabled using the above method then
+ * this API has no effect and clients are allowed to associate to the AP (within limit of
+ * max number of clients).
+ *
+ * If client control by user is enabled then this API this API configures the list of
+ * clients which are blocked. These are rejected.
+ *
* All other clients which attempt to associate, whose MAC addresses are on neither list,
* are:
* <ul>
@@ -927,23 +953,11 @@
* </ul>
*
* @param blockedClientList list of clients which are not allowed to associate to the AP.
- * @param allowedClientList list of clients which are allowed to associate to the AP
- * without user pre-approval.
* @return Builder for chaining.
*/
@NonNull
- public Builder setClientList(@NonNull List<MacAddress> blockedClientList,
- @NonNull List<MacAddress> allowedClientList) {
+ public Builder setBlockedClientList(@NonNull List<MacAddress> blockedClientList) {
mBlockedClientList = new ArrayList<>(blockedClientList);
- mAllowedClientList = new ArrayList<>(allowedClientList);
- Iterator<MacAddress> iterator = mAllowedClientList.iterator();
- while (iterator.hasNext()) {
- MacAddress client = iterator.next();
- int index = mBlockedClientList.indexOf(client);
- if (index != -1) {
- throw new IllegalArgumentException("A MacAddress exist in both list");
- }
- }
return this;
}
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index e0b433d..ba68d17 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -635,13 +635,6 @@
public String preSharedKey;
/**
- * Optional SAE Password Id for use with WPA3-SAE. It is an ASCII string.
- * @hide
- */
- @SystemApi
- public @Nullable String saePasswordId;
-
- /**
* Four WEP keys. For each of the four values, provide either an ASCII
* string enclosed in double quotation marks (e.g., {@code "abcdef"}),
* a string of hex digits (e.g., {@code 0102030405}), or an empty string
@@ -2334,9 +2327,6 @@
sbuf.append('*');
}
- sbuf.append('\n').append(" SAE Password Id: ");
- sbuf.append(this.saePasswordId);
-
sbuf.append("\nEnterprise config:\n");
sbuf.append(enterpriseConfig);
@@ -2731,7 +2721,6 @@
providerFriendlyName = source.providerFriendlyName;
isHomeProviderNetwork = source.isHomeProviderNetwork;
preSharedKey = source.preSharedKey;
- saePasswordId = source.saePasswordId;
mNetworkSelectionStatus.copy(source.getNetworkSelectionStatus());
apBand = source.apBand;
@@ -2819,7 +2808,6 @@
dest.writeLong(roamingConsortiumId);
}
dest.writeString(preSharedKey);
- dest.writeString(saePasswordId);
for (String wepKey : wepKeys) {
dest.writeString(wepKey);
}
@@ -2895,7 +2883,6 @@
config.roamingConsortiumIds[i] = in.readLong();
}
config.preSharedKey = in.readString();
- config.saePasswordId = in.readString();
for (int i = 0; i < config.wepKeys.length; i++) {
config.wepKeys[i] = in.readString();
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 96beacd..e1acaf8 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -727,8 +727,9 @@
/**
* If Soft Ap client is blocked, this reason code means that client doesn't exist in the
- * specified configuration {@link SoftApConfiguration.Builder#setClientList(List, List)}
- * and the {@link SoftApConfiguration.Builder#enableClientControlByUser(true)}
+ * specified configuration {@link SoftApConfiguration.Builder#setBlockedClientList(List)}
+ * and {@link SoftApConfiguration.Builder#setAllowedClientList(List)}
+ * and the {@link SoftApConfiguration.Builder#setClientControlByUserEnabled(boolean)}
* is configured as well.
* @hide
*/
@@ -1352,7 +1353,7 @@
try {
ParceledListSlice<WifiConfiguration> parceledList =
mService.getConfiguredNetworks(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
if (parceledList == null) {
return Collections.emptyList();
}
@@ -1369,7 +1370,7 @@
try {
ParceledListSlice<WifiConfiguration> parceledList =
mService.getPrivilegedConfiguredNetworks(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
if (parceledList == null) {
return Collections.emptyList();
}
@@ -1898,7 +1899,7 @@
@NonNull List<WifiNetworkSuggestion> networkSuggestions) {
try {
return mService.addNetworkSuggestions(
- networkSuggestions, mContext.getOpPackageName(), mContext.getFeatureId());
+ networkSuggestions, mContext.getOpPackageName(), mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2680,8 +2681,8 @@
public boolean startScan(WorkSource workSource) {
try {
String packageName = mContext.getOpPackageName();
- String featureId = mContext.getFeatureId();
- return mService.startScan(packageName, featureId);
+ String attributionTag = mContext.getAttributionTag();
+ return mService.startScan(packageName, attributionTag);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2713,7 +2714,7 @@
public WifiInfo getConnectionInfo() {
try {
return mService.getConnectionInfo(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2728,7 +2729,7 @@
public List<ScanResult> getScanResults() {
try {
return mService.getScanResults(mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2759,7 +2760,7 @@
try {
return mService.getMatchingScanResults(
networkSuggestionsToMatch, scanResults,
- mContext.getOpPackageName(), mContext.getFeatureId());
+ mContext.getOpPackageName(), mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3198,7 +3199,7 @@
new LocalOnlyHotspotCallbackProxy(this, executor, callback);
try {
String packageName = mContext.getOpPackageName();
- String featureId = mContext.getFeatureId();
+ String featureId = mContext.getAttributionTag();
int returnCode = mService.startLocalOnlyHotspot(proxy, packageName, featureId,
config);
if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) {
@@ -3409,9 +3410,10 @@
* If the API is called while the tethered soft AP is enabled, the configuration will apply to
* the current soft AP if the new configuration only includes
* {@link SoftApConfiguration.Builder#setMaxNumberOfClients(int)}
- * or {@link SoftApConfiguration.Builder#setShutdownTimeoutMillis(int)}
- * or {@link SoftApConfiguration.Builder#enableClientControlByUser(boolean)}
- * or {@link SoftApConfiguration.Builder#setClientList(List, List)}.
+ * or {@link SoftApConfiguration.Builder#setShutdownTimeoutMillis(long)}
+ * or {@link SoftApConfiguration.Builder#setClientControlByUserEnabled(boolean)}
+ * or {@link SoftApConfiguration.Builder#setBlockedClientList(List)}
+ * or {@link SoftApConfiguration.Builder#setAllowedClientList(List)}
*
* Otherwise, the configuration changes will be applied when the Soft AP is next started
* (the framework will not stop/start the AP).
@@ -5889,7 +5891,7 @@
try {
mService.registerSuggestionConnectionStatusListener(new Binder(),
new SuggestionConnectionStatusListenerProxy(executor, listener),
- listener.hashCode(), mContext.getOpPackageName(), mContext.getFeatureId());
+ listener.hashCode(), mContext.getOpPackageName(), mContext.getAttributionTag());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 5e48919..d299cdc 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -182,7 +182,7 @@
public List<Integer> getAvailableChannels(int band) {
try {
Bundle bundle = mService.getAvailableChannels(band, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mContext.getAttributionTag());
List<Integer> channels = bundle.getIntegerArrayList(GET_AVAILABLE_CHANNELS_EXTRA);
return channels == null ? new ArrayList<>() : channels;
} catch (RemoteException e) {
@@ -963,7 +963,7 @@
scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
- scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getFeatureId());
+ scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getAttributionTag());
mAsyncChannel.sendMessage(CMD_START_BACKGROUND_SCAN, 0, key, scanParams);
}
@@ -984,7 +984,7 @@
validateChannel();
Bundle scanParams = new Bundle();
scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
- scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getFeatureId());
+ scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getAttributionTag());
mAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, key, scanParams);
}
@@ -1001,7 +1001,7 @@
validateChannel();
Bundle scanParams = new Bundle();
scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
- scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getFeatureId());
+ scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getAttributionTag());
Message reply =
mAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0, 0, scanParams);
return reply.what == CMD_OP_SUCCEEDED;
@@ -1056,7 +1056,7 @@
scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
- scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getFeatureId());
+ scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getAttributionTag());
mAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, scanParams);
}
@@ -1073,7 +1073,7 @@
validateChannel();
Bundle scanParams = new Bundle();
scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
- scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getFeatureId());
+ scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getAttributionTag());
mAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, key, scanParams);
}
@@ -1086,7 +1086,7 @@
validateChannel();
Bundle scanParams = new Bundle();
scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
- scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getFeatureId());
+ scanParams.putString(REQUEST_FEATURE_ID_KEY, mContext.getAttributionTag());
Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SINGLE_SCAN_RESULTS, 0, 0,
scanParams);
if (reply.what == WifiScanner.CMD_OP_SUCCEEDED) {
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 2ebaa18..c2ae17c 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -267,7 +267,7 @@
try {
Binder binder = new Binder();
- mService.connect(binder, mContext.getOpPackageName(), mContext.getFeatureId(),
+ mService.connect(binder, mContext.getOpPackageName(), mContext.getAttributionTag(),
new WifiAwareEventCallbackProxy(this, looper, binder, attachCallback,
identityChangedListener), configRequest,
identityChangedListener != null);
@@ -298,7 +298,7 @@
}
try {
- mService.publish(mContext.getOpPackageName(), mContext.getFeatureId(), clientId,
+ mService.publish(mContext.getOpPackageName(), mContext.getAttributionTag(), clientId,
publishConfig,
new WifiAwareDiscoverySessionCallbackProxy(this, looper, true, callback,
clientId));
@@ -336,7 +336,7 @@
}
try {
- mService.subscribe(mContext.getOpPackageName(), mContext.getFeatureId(), clientId,
+ mService.subscribe(mContext.getOpPackageName(), mContext.getAttributionTag(), clientId,
subscribeConfig,
new WifiAwareDiscoverySessionCallbackProxy(this, looper, false, callback,
clientId));
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index a310ff6..724ccf0 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -1180,7 +1180,7 @@
== AsyncChannel.STATUS_SUCCESSFUL) {
Bundle bundle = new Bundle();
bundle.putString(CALLING_PACKAGE, c.mContext.getOpPackageName());
- bundle.putString(CALLING_FEATURE_ID, c.mContext.getFeatureId());
+ bundle.putString(CALLING_FEATURE_ID, c.mContext.getAttributionTag());
bundle.putBinder(CALLING_BINDER, binder);
c.mAsyncChannel.sendMessage(UPDATE_CHANNEL_INFO, 0,
c.putListener(null), bundle);
diff --git a/wifi/java/android/net/wifi/rtt/WifiRttManager.java b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
index cb0c5d4..865702a 100644
--- a/wifi/java/android/net/wifi/rtt/WifiRttManager.java
+++ b/wifi/java/android/net/wifi/rtt/WifiRttManager.java
@@ -146,8 +146,8 @@
Binder binder = new Binder();
try {
- mService.startRanging(binder, mContext.getOpPackageName(), mContext.getFeatureId(),
- workSource, request, new IRttCallback.Stub() {
+ mService.startRanging(binder, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), workSource, request, new IRttCallback.Stub() {
@Override
public void onRangingFailure(int status) throws RemoteException {
clearCallingIdentity();
diff --git a/wifi/tests/AndroidTest.xml b/wifi/tests/AndroidTest.xml
index 987fee7..34e2e3a 100644
--- a/wifi/tests/AndroidTest.xml
+++ b/wifi/tests/AndroidTest.xml
@@ -25,4 +25,10 @@
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
+
+ <!-- Only run FrameworksWifiApiTests in MTS if the Wifi Mainline module is installed. -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="mainline-module-package-name" value="com.google.android.wifi" />
+ </object>
</configuration>
diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
index 060ddf0..1a44270 100644
--- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
@@ -127,8 +127,9 @@
.setMaxNumberOfClients(10)
.setAutoShutdownEnabled(true)
.setShutdownTimeoutMillis(500000)
- .enableClientControlByUser(true)
- .setClientList(testBlockedClientList, testAllowedClientList)
+ .setClientControlByUserEnabled(true)
+ .setBlockedClientList(testBlockedClientList)
+ .setAllowedClientList(testAllowedClientList)
.build();
assertThat(original.getPassphrase()).isEqualTo("secretsecret");
assertThat(original.getSecurityType()).isEqualTo(
@@ -264,7 +265,9 @@
ArrayList<MacAddress> testBlockedClientList = new ArrayList<>();
testBlockedClientList.add(testMacAddress_1);
SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
- configBuilder.setClientList(testBlockedClientList, testAllowedClientList);
+ configBuilder.setBlockedClientList(testBlockedClientList)
+ .setAllowedClientList(testAllowedClientList)
+ .build();
}
@Test
diff --git a/wifi/tests/src/android/net/wifi/WifiScannerTest.java b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
index 0cc76b6..4881200 100644
--- a/wifi/tests/src/android/net/wifi/WifiScannerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
@@ -267,7 +267,7 @@
assertNull(messageBundle.getParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY));
assertEquals(mContext.getOpPackageName(),
messageBundle.getParcelable(WifiScanner.REQUEST_PACKAGE_NAME_KEY));
- assertEquals(mContext.getFeatureId(),
+ assertEquals(mContext.getAttributionTag(),
messageBundle.getParcelable(WifiScanner.REQUEST_FEATURE_ID_KEY));
}
@@ -297,7 +297,7 @@
Bundle messageBundle = (Bundle) message.obj;
assertEquals(mContext.getOpPackageName(),
messageBundle.getParcelable(WifiScanner.REQUEST_PACKAGE_NAME_KEY));
- assertEquals(mContext.getFeatureId(),
+ assertEquals(mContext.getAttributionTag(),
messageBundle.getParcelable(WifiScanner.REQUEST_FEATURE_ID_KEY));
}
diff --git a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
index a9dcde0..e6eae41 100644
--- a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
@@ -71,7 +71,7 @@
mMockLooperExecutor = mMockLooper.getNewExecutor();
when(mockContext.getOpPackageName()).thenReturn(packageName);
- when(mockContext.getFeatureId()).thenReturn(featureId);
+ when(mockContext.getAttributionTag()).thenReturn(featureId);
}
/**