Merge "Fix serialization issue of ExternalVibration"
diff --git a/api/current.txt b/api/current.txt
index 1e840dd..ac69f6f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -479,6 +479,7 @@
field public static final int countDown = 16844059; // 0x101051b
field public static final int country = 16843962; // 0x10104ba
field public static final int cropToPadding = 16843043; // 0x1010123
+ field public static final int crossProfile = 16844303; // 0x101060f
field public static final int cursorVisible = 16843090; // 0x1010152
field public static final int customNavigationLayout = 16843474; // 0x10102d2
field public static final int customTokens = 16843579; // 0x101033b
@@ -7127,6 +7128,7 @@
field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
+ field public static final int TAG_CAMERA_POLICY_SET = 210034; // 0x33472
field public static final int TAG_CERT_AUTHORITY_INSTALLED = 210029; // 0x3346d
field public static final int TAG_CERT_AUTHORITY_REMOVED = 210030; // 0x3346e
field public static final int TAG_CERT_VALIDATION_FAILURE = 210033; // 0x33471
@@ -36094,6 +36096,37 @@
method public int getUserOperationResult();
}
+ public final class VibrationAttributes implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getFlags();
+ method public int getUsage();
+ method public int getUsageClass();
+ method public boolean isFlagSet(int);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationAttributes> CREATOR;
+ field public static final int FLAG_BYPASS_INTERRUPTION_POLICY = 1; // 0x1
+ field public static final int USAGE_ALARM = 17; // 0x11
+ field public static final int USAGE_CLASS_ALARM = 1; // 0x1
+ field public static final int USAGE_CLASS_FEEDBACK = 2; // 0x2
+ field public static final int USAGE_CLASS_MASK = 15; // 0xf
+ field public static final int USAGE_CLASS_UNKNOWN = 0; // 0x0
+ field public static final int USAGE_COMMUNICATION_REQUEST = 65; // 0x41
+ field public static final int USAGE_HARDWARE_FEEDBACK = 50; // 0x32
+ field public static final int USAGE_NOTIFICATION = 49; // 0x31
+ field public static final int USAGE_PHYSICAL_EMULATION = 34; // 0x22
+ field public static final int USAGE_RINGTONE = 33; // 0x21
+ field public static final int USAGE_TOUCH = 18; // 0x12
+ field public static final int USAGE_UNKNOWN = 0; // 0x0
+ }
+
+ public static final class VibrationAttributes.Builder {
+ ctor public VibrationAttributes.Builder();
+ ctor public VibrationAttributes.Builder(@Nullable android.os.VibrationAttributes);
+ method @NonNull public android.os.VibrationAttributes build();
+ method @NonNull public android.os.VibrationAttributes.Builder replaceFlags(int);
+ method @NonNull public android.os.VibrationAttributes.Builder setUsage(int);
+ }
+
public abstract class VibrationEffect implements android.os.Parcelable {
method public static android.os.VibrationEffect createOneShot(long, int);
method @NonNull public static android.os.VibrationEffect createPredefined(int);
@@ -45560,6 +45593,7 @@
method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
method public void onMessageWaitingIndicatorChanged(boolean);
method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
+ method public void onRegistrationFailed(@NonNull android.telephony.CellIdentity, @NonNull String, int, int, int);
method public void onServiceStateChanged(android.telephony.ServiceState);
method @Deprecated public void onSignalStrengthChanged(int);
method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
@@ -45577,6 +45611,7 @@
field public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4
field public static final int LISTEN_NONE = 0; // 0x0
field @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
+ field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 1073741824; // 0x40000000
field public static final int LISTEN_SERVICE_STATE = 1; // 0x1
field @Deprecated public static final int LISTEN_SIGNAL_STRENGTH = 2; // 0x2
field public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100
diff --git a/api/system-current.txt b/api/system-current.txt
index 653df73..766daab 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -413,6 +413,16 @@
field public static final int UID_STATE_TOP = 200; // 0xc8
}
+ public static final class AppOpsManager.HistoricalFeatureOps 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 public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalFeatureOps> CREATOR;
+ }
+
public static final class AppOpsManager.HistoricalOp implements android.os.Parcelable {
method public int describeContents();
method public long getAccessCount(int, int, int);
@@ -446,6 +456,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 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);
@@ -454,6 +465,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.HistoricalOp getOp(@NonNull String);
method @NonNull public android.app.AppOpsManager.HistoricalOp getOpAt(@IntRange(from=0) int);
method @IntRange(from=0) public int getOpCount();
@@ -4141,6 +4155,14 @@
}
+package android.media.audiofx {
+
+ public class AudioEffect {
+ ctor @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public AudioEffect(@NonNull java.util.UUID, @NonNull android.media.AudioDeviceAddress);
+ }
+
+}
+
package android.media.audiopolicy {
public class AudioMix {
@@ -7807,7 +7829,7 @@
field public static final String SERIAL_NUMBER = "serial_number";
field public static final String SERVICE_CATEGORY = "service_category";
field public static final String SLOT_INDEX = "slot_index";
- field public static final String SUB_ID = "sub_id";
+ field public static final String SUBSCRIPTION_ID = "sub_id";
}
public static final class Telephony.CellBroadcasts.Preference {
@@ -9617,7 +9639,9 @@
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.NetworkRegistrationInfo> CREATOR;
field public static final int DOMAIN_CS = 1; // 0x1
+ field public static final int DOMAIN_CS_PS = 3; // 0x3
field public static final int DOMAIN_PS = 2; // 0x2
+ field public static final int DOMAIN_UNKNOWN = 0; // 0x0
field public static final int REGISTRATION_STATE_DENIED = 3; // 0x3
field public static final int REGISTRATION_STATE_HOME = 1; // 0x1
field public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0; // 0x0
@@ -10251,6 +10275,7 @@
method public void addOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyCallStateChangedForAllSubscriptions(int, @Nullable String);
method public void notifyCarrierNetworkChange(boolean);
+ method public void notifyRegistrationFailed(int, int, @NonNull android.telephony.CellIdentity, @NonNull String, int, int, int);
method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
method public void removeOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 1c1d794..7ba943c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -244,6 +244,16 @@
field public static final int UID_STATE_TOP = 200; // 0xc8
}
+ public static final class AppOpsManager.HistoricalFeatureOps 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 public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalFeatureOps> CREATOR;
+ }
+
public static final class AppOpsManager.HistoricalOp implements android.os.Parcelable {
method public int describeContents();
method public long getAccessCount(int, int, int);
@@ -268,9 +278,9 @@
method @IntRange(from=0) public int getUidCount();
method @Nullable public android.app.AppOpsManager.HistoricalUidOps getUidOps(int);
method @NonNull public android.app.AppOpsManager.HistoricalUidOps getUidOpsAt(@IntRange(from=0) int);
- method public void increaseAccessCount(int, int, @NonNull String, int, int, long);
- method public void increaseAccessDuration(int, int, @NonNull String, int, int, long);
- method public void increaseRejectCount(int, int, @NonNull String, int, int, long);
+ method public void increaseAccessCount(int, int, @NonNull String, @Nullable String, int, int, long);
+ method public void increaseAccessDuration(int, int, @NonNull String, @Nullable String, int, int, long);
+ method public void increaseRejectCount(int, int, @NonNull String, @Nullable String, int, int, long);
method public void offsetBeginAndEndTime(long);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR;
@@ -282,6 +292,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 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);
@@ -290,6 +301,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.HistoricalOp getOp(@NonNull String);
method @NonNull public android.app.AppOpsManager.HistoricalOp getOpAt(@IntRange(from=0) int);
method @IntRange(from=0) public int getOpCount();
@@ -2183,6 +2197,14 @@
field public static final String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
}
+ public final class VibrationAttributes implements android.os.Parcelable {
+ method @Deprecated @NonNull public android.media.AudioAttributes getAudioAttributes();
+ }
+
+ public static final class VibrationAttributes.Builder {
+ ctor public VibrationAttributes.Builder(@NonNull android.media.AudioAttributes, @Nullable android.os.VibrationEffect);
+ }
+
public abstract class VibrationEffect implements android.os.Parcelable {
method public static android.os.VibrationEffect get(int);
method public static android.os.VibrationEffect get(int, boolean);
@@ -2602,7 +2624,7 @@
field public static final String SERIAL_NUMBER = "serial_number";
field public static final String SERVICE_CATEGORY = "service_category";
field public static final String SLOT_INDEX = "slot_index";
- field public static final String SUB_ID = "sub_id";
+ field public static final String SUBSCRIPTION_ID = "sub_id";
}
public static final class Telephony.Sms.Intents {
@@ -3170,7 +3192,9 @@
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.NetworkRegistrationInfo> CREATOR;
field public static final int DOMAIN_CS = 1; // 0x1
+ field public static final int DOMAIN_CS_PS = 3; // 0x3
field public static final int DOMAIN_PS = 2; // 0x2
+ field public static final int DOMAIN_UNKNOWN = 0; // 0x0
field public static final int REGISTRATION_STATE_DENIED = 3; // 0x3
field public static final int REGISTRATION_STATE_HOME = 1; // 0x1
field public static final int REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING = 0; // 0x0
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 42c4d36..4a8e4e2 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -3917,10 +3917,53 @@
void visitHistoricalOps(@NonNull HistoricalOps ops);
void visitHistoricalUidOps(@NonNull HistoricalUidOps ops);
void visitHistoricalPackageOps(@NonNull HistoricalPackageOps ops);
+ void visitHistoricalFeatureOps(@NonNull HistoricalFeatureOps ops);
void visitHistoricalOp(@NonNull HistoricalOp ops);
}
/**
+ * Specifies what parameters to filter historical appop requests for
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "FILTER_BY_" }, value = {
+ FILTER_BY_UID,
+ FILTER_BY_PACKAGE_NAME,
+ FILTER_BY_FEATURE_ID,
+ FILTER_BY_OP_NAMES
+ })
+ public @interface HistoricalOpsRequestFilter {}
+
+ /**
+ * Filter historical appop request by uid.
+ *
+ * @hide
+ */
+ public static final int FILTER_BY_UID = 1<<0;
+
+ /**
+ * Filter historical appop request by package name.
+ *
+ * @hide
+ */
+ public static final int FILTER_BY_PACKAGE_NAME = 1<<1;
+
+ /**
+ * Filter historical appop request by feature id.
+ *
+ * @hide
+ */
+ public static final int FILTER_BY_FEATURE_ID = 1<<2;
+
+ /**
+ * Filter historical appop request by op names.
+ *
+ * @hide
+ */
+ public static final int FILTER_BY_OP_NAMES = 1<<3;
+
+ /**
* Request for getting historical app op usage. The request acts
* as a filtering criteria when querying historical op usage.
*
@@ -3932,17 +3975,22 @@
public static final class HistoricalOpsRequest {
private final int mUid;
private final @Nullable String mPackageName;
+ private final @Nullable String mFeatureId;
private final @Nullable List<String> mOpNames;
+ private final @HistoricalOpsRequestFilter int mFilter;
private final long mBeginTimeMillis;
private final long mEndTimeMillis;
private final @OpFlags int mFlags;
private HistoricalOpsRequest(int uid, @Nullable String packageName,
- @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
- @OpFlags int flags) {
+ @Nullable String featureId, @Nullable List<String> opNames,
+ @HistoricalOpsRequestFilter int filter, long beginTimeMillis,
+ long endTimeMillis, @OpFlags int flags) {
mUid = uid;
mPackageName = packageName;
+ mFeatureId = featureId;
mOpNames = opNames;
+ mFilter = filter;
mBeginTimeMillis = beginTimeMillis;
mEndTimeMillis = endTimeMillis;
mFlags = flags;
@@ -3958,7 +4006,9 @@
public static final class Builder {
private int mUid = Process.INVALID_UID;
private @Nullable String mPackageName;
+ private @Nullable String mFeatureId;
private @Nullable List<String> mOpNames;
+ private @HistoricalOpsRequestFilter int mFilter;
private final long mBeginTimeMillis;
private final long mEndTimeMillis;
private @OpFlags int mFlags = OP_FLAGS_ALL;
@@ -3991,6 +4041,13 @@
Preconditions.checkArgument(uid == Process.INVALID_UID || uid >= 0,
"uid must be " + Process.INVALID_UID + " or non negative");
mUid = uid;
+
+ if (uid == Process.INVALID_UID) {
+ mFilter &= ~FILTER_BY_UID;
+ } else {
+ mFilter |= FILTER_BY_UID;
+ }
+
return this;
}
@@ -4002,6 +4059,26 @@
*/
public @NonNull Builder setPackageName(@Nullable String packageName) {
mPackageName = packageName;
+
+ if (packageName == null) {
+ mFilter &= ~FILTER_BY_PACKAGE_NAME;
+ } else {
+ mFilter |= FILTER_BY_PACKAGE_NAME;
+ }
+
+ return this;
+ }
+
+ /**
+ * Sets the feature id to query for.
+ *
+ * @param featureId The id of the feature.
+ * @return This builder.
+ */
+ public @NonNull Builder setFeatureId(@Nullable String featureId) {
+ mFeatureId = featureId;
+ mFilter |= FILTER_BY_FEATURE_ID;
+
return this;
}
@@ -4020,6 +4097,13 @@
}
}
mOpNames = opNames;
+
+ if (mOpNames == null) {
+ mFilter &= ~FILTER_BY_OP_NAMES;
+ } else {
+ mFilter |= FILTER_BY_OP_NAMES;
+ }
+
return this;
}
@@ -4044,8 +4128,8 @@
* @return a new {@link HistoricalOpsRequest}.
*/
public @NonNull HistoricalOpsRequest build() {
- return new HistoricalOpsRequest(mUid, mPackageName, mOpNames,
- mBeginTimeMillis, mEndTimeMillis, mFlags);
+ return new HistoricalOpsRequest(mUid, mPackageName, mFeatureId, mOpNames,
+ mFilter, mBeginTimeMillis, mEndTimeMillis, mFlags);
}
}
}
@@ -4202,15 +4286,18 @@
/**
* AppPermissionUsage the ops to leave only the data we filter for.
*
- * @param uid Uid to filter for or {@link android.os.Process#INCIDENTD_UID} for all.
- * @param packageName Package to filter for or null for all.
- * @param opNames Ops to filter for or null for all.
+ * @param uid Uid to filter for.
+ * @param packageName Package to filter for.
+ * @param featureId Package 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.
* @param endTimeMillis The end time to filter for or {@link Long#MAX_VALUE} for all.
*
* @hide
*/
- public void filter(int uid, @Nullable String packageName, @Nullable String[] opNames,
+ public void filter(int uid, @Nullable String packageName, @Nullable String featureId,
+ @Nullable String[] opNames, @HistoricalOpsRequestFilter int filter,
long beginTimeMillis, long endTimeMillis) {
final long durationMillis = getDurationMillis();
mBeginTimeMillis = Math.max(mBeginTimeMillis, beginTimeMillis);
@@ -4220,10 +4307,10 @@
final int uidCount = getUidCount();
for (int i = uidCount - 1; i >= 0; i--) {
final HistoricalUidOps uidOp = mHistoricalUidOps.valueAt(i);
- if (uid != Process.INVALID_UID && uid != uidOp.getUid()) {
+ if ((filter & FILTER_BY_UID) != 0 && uid != uidOp.getUid()) {
mHistoricalUidOps.removeAt(i);
} else {
- uidOp.filter(packageName, opNames, scaleFactor);
+ uidOp.filter(packageName, featureId, opNames, filter, scaleFactor);
}
}
}
@@ -4251,25 +4338,28 @@
/** @hide */
@TestApi
public void increaseAccessCount(int opCode, int uid, @NonNull String packageName,
- @UidState int uidState, @OpFlags int flags, long increment) {
+ @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ long increment) {
getOrCreateHistoricalUidOps(uid).increaseAccessCount(opCode,
- packageName, uidState, flags, increment);
+ packageName, featureId, uidState, flags, increment);
}
/** @hide */
@TestApi
public void increaseRejectCount(int opCode, int uid, @NonNull String packageName,
- @UidState int uidState, @OpFlags int flags, long increment) {
+ @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ long increment) {
getOrCreateHistoricalUidOps(uid).increaseRejectCount(opCode,
- packageName, uidState, flags, increment);
+ packageName, featureId, uidState, flags, increment);
}
/** @hide */
@TestApi
public void increaseAccessDuration(int opCode, int uid, @NonNull String packageName,
- @UidState int uidState, @OpFlags int flags, long increment) {
+ @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ long increment) {
getOrCreateHistoricalUidOps(uid).increaseAccessDuration(opCode,
- packageName, uidState, flags, increment);
+ packageName, featureId, uidState, flags, increment);
}
/** @hide */
@@ -4549,15 +4639,17 @@
}
}
- private void filter(@Nullable String packageName, @Nullable String[] opNames,
+ private void filter(@Nullable String packageName, @Nullable String featureId,
+ @Nullable String[] opNames, @HistoricalOpsRequestFilter int filter,
double fractionToRemove) {
final int packageCount = getPackageCount();
for (int i = packageCount - 1; i >= 0; i--) {
final HistoricalPackageOps packageOps = getPackageOpsAt(i);
- if (packageName != null && !packageName.equals(packageOps.getPackageName())) {
+ if ((filter & FILTER_BY_PACKAGE_NAME) != 0 && !packageName.equals(
+ packageOps.getPackageName())) {
mHistoricalPackageOps.removeAt(i);
} else {
- packageOps.filter(opNames, fractionToRemove);
+ packageOps.filter(featureId, opNames, filter, fractionToRemove);
}
}
}
@@ -4574,21 +4666,24 @@
}
private void increaseAccessCount(int opCode, @NonNull String packageName,
- @UidState int uidState, @OpFlags int flags, long increment) {
+ @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ long increment) {
getOrCreateHistoricalPackageOps(packageName).increaseAccessCount(
- opCode, uidState, flags, increment);
+ opCode, featureId, uidState, flags, increment);
}
private void increaseRejectCount(int opCode, @NonNull String packageName,
- @UidState int uidState, @OpFlags int flags, long increment) {
+ @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ long increment) {
getOrCreateHistoricalPackageOps(packageName).increaseRejectCount(
- opCode, uidState, flags, increment);
+ opCode, featureId, uidState, flags, increment);
}
private void increaseAccessDuration(int opCode, @NonNull String packageName,
- @UidState int uidState, @OpFlags int flags, long increment) {
+ @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ long increment) {
getOrCreateHistoricalPackageOps(packageName).increaseAccessDuration(
- opCode, uidState, flags, increment);
+ opCode, featureId, uidState, flags, increment);
}
/**
@@ -4733,7 +4828,7 @@
@SystemApi
public static final class HistoricalPackageOps implements Parcelable {
private final @NonNull String mPackageName;
- private @Nullable ArrayMap<String, HistoricalOp> mHistoricalOps;
+ private @Nullable ArrayMap<String, HistoricalFeatureOps> mHistoricalFeatureOps;
/** @hide */
public HistoricalPackageOps(@NonNull String packageName) {
@@ -4742,6 +4837,339 @@
private HistoricalPackageOps(@NonNull HistoricalPackageOps other) {
mPackageName = other.mPackageName;
+ final int opCount = other.getFeatureCount();
+ 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);
+ }
+ mHistoricalFeatureOps.put(cloneOps.getFeatureId(), cloneOps);
+ }
+ }
+
+ private HistoricalPackageOps(@NonNull Parcel parcel) {
+ mPackageName = parcel.readString();
+ mHistoricalFeatureOps = parcel.createTypedArrayMap(HistoricalFeatureOps.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);
+ if (spliceOps != null) {
+ if (splice == null) {
+ splice = new HistoricalPackageOps(mPackageName);
+ }
+ if (splice.mHistoricalFeatureOps == null) {
+ splice.mHistoricalFeatureOps = new ArrayMap<>();
+ }
+ splice.mHistoricalFeatureOps.put(spliceOps.getFeatureId(), 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);
+ } else {
+ if (mHistoricalFeatureOps == null) {
+ mHistoricalFeatureOps = new ArrayMap<>();
+ }
+ mHistoricalFeatureOps.put(otherFeatureOps.getFeatureId(), otherFeatureOps);
+ }
+ }
+ }
+
+ private void filter(@Nullable String featureId, @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);
+ } else {
+ featureOps.filter(opNames, filter, fractionToRemove);
+ }
+ }
+ }
+
+ private void accept(@NonNull HistoricalOpsVisitor visitor) {
+ visitor.visitHistoricalPackageOps(this);
+ final int featureCount = getFeatureCount();
+ for (int i = 0; i < featureCount; i++) {
+ getFeatureOpsAt(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()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void increaseAccessCount(int opCode, @Nullable String featureId,
+ @UidState int uidState, @OpFlags int flags, long increment) {
+ getOrCreateHistoricalFeatureOps(featureId).increaseAccessCount(
+ opCode, uidState, flags, increment);
+ }
+
+ private void increaseRejectCount(int opCode, @Nullable String featureId,
+ @UidState int uidState, @OpFlags int flags, long increment) {
+ getOrCreateHistoricalFeatureOps(featureId).increaseRejectCount(
+ opCode, uidState, flags, increment);
+ }
+
+ private void increaseAccessDuration(int opCode, @Nullable String featureId,
+ @UidState int uidState, @OpFlags int flags, long increment) {
+ getOrCreateHistoricalFeatureOps(featureId).increaseAccessDuration(
+ opCode, uidState, flags, increment);
+ }
+
+ /**
+ * Gets the package name which the data represents.
+ *
+ * @return The package name which the data represents.
+ */
+ public @NonNull String getPackageName() {
+ return mPackageName;
+ }
+
+ private @NonNull HistoricalFeatureOps getOrCreateHistoricalFeatureOps(
+ @Nullable String featureId) {
+ if (mHistoricalFeatureOps == null) {
+ mHistoricalFeatureOps = new ArrayMap<>();
+ }
+ HistoricalFeatureOps historicalFeatureOp = mHistoricalFeatureOps.get(featureId);
+ if (historicalFeatureOp == null) {
+ historicalFeatureOp = new HistoricalFeatureOps(featureId);
+ mHistoricalFeatureOps.put(featureId, historicalFeatureOp);
+ }
+ return historicalFeatureOp;
+ }
+
+ /**
+ * Gets number historical app ops.
+ *
+ * @return The number historical app ops.
+ * @see #getOpAt(int)
+ */
+ public @IntRange(from = 0) int getOpCount() {
+ int numOps = 0;
+ int numFeatures = getFeatureCount();
+
+ 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) {
+ numOps++;
+ break;
+ }
+ }
+ }
+
+ return numOps;
+ }
+
+ /**
+ * Gets the historical op at a given index.
+ *
+ * <p>This combines the counts from all features.
+ *
+ * @param index The index to lookup.
+ * @return The op at the given index.
+ * @see #getOpCount()
+ */
+ public @NonNull HistoricalOp getOpAt(@IntRange(from = 0) int index) {
+ int numOpsFound = 0;
+ int numFeatures = getFeatureCount();
+
+ 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) {
+ if (numOpsFound == index) {
+ return getOp(opName);
+ } else {
+ numOpsFound++;
+ break;
+ }
+ }
+ }
+ }
+
+ throw new IndexOutOfBoundsException();
+ }
+
+ /**
+ * Gets the historical entry for a given op name.
+ *
+ * <p>This combines the counts from all features.
+ *
+ * @param opName The op name.
+ * @return The historical entry for that op name.
+ */
+ public @Nullable HistoricalOp getOp(@NonNull String opName) {
+ if (mHistoricalFeatureOps == 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) {
+ if (combinedOp == null) {
+ combinedOp = new HistoricalOp(featureOp);
+ } else {
+ combinedOp.merge(featureOp);
+ }
+ }
+ }
+
+ return combinedOp;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int flags) {
+ parcel.writeString(mPackageName);
+ parcel.writeTypedArrayMap(mHistoricalFeatureOps, flags);
+ }
+
+ public static final @android.annotation.NonNull Creator<HistoricalPackageOps> CREATOR =
+ new Creator<HistoricalPackageOps>() {
+ @Override
+ public @NonNull HistoricalPackageOps createFromParcel(@NonNull Parcel parcel) {
+ return new HistoricalPackageOps(parcel);
+ }
+
+ @Override
+ public @NonNull HistoricalPackageOps[] newArray(int size) {
+ return new HistoricalPackageOps[size];
+ }
+ };
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final HistoricalPackageOps other = (HistoricalPackageOps) obj;
+ if (!mPackageName.equals(other.mPackageName)) {
+ return false;
+ }
+ if (mHistoricalFeatureOps == null) {
+ if (other.mHistoricalFeatureOps != null) {
+ return false;
+ }
+ } else if (!mHistoricalFeatureOps.equals(other.mHistoricalFeatureOps)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mPackageName != null ? mPackageName.hashCode() : 0;
+ result = 31 * result + (mHistoricalFeatureOps != null ? mHistoricalFeatureOps.hashCode()
+ : 0);
+ return result;
+ }
+
+ /**
+ * Gets number of feature with historical ops.
+ *
+ * @return The number of feature with historical ops.
+ *
+ * @see #getFeatureOpsAt(int)
+ */
+ public @IntRange(from = 0) int getFeatureCount() {
+ if (mHistoricalFeatureOps == null) {
+ return 0;
+ }
+ return mHistoricalFeatureOps.size();
+ }
+
+ /**
+ * Gets the historical feature ops at a given index.
+ *
+ * @param index The index.
+ *
+ * @return The historical feature ops at the given index.
+ *
+ * @see #getFeatureCount()
+ */
+ public @NonNull HistoricalFeatureOps getFeatureOpsAt(@IntRange(from = 0) int index) {
+ if (mHistoricalFeatureOps == null) {
+ throw new IndexOutOfBoundsException();
+ }
+ return mHistoricalFeatureOps.valueAt(index);
+ }
+
+ /**
+ * Gets the historical feature ops for a given feature.
+ *
+ * @param featureId The feature id.
+ *
+ * @return The historical ops for the feature.
+ */
+ public @Nullable HistoricalFeatureOps getFeatureOps(@NonNull String featureId) {
+ if (mHistoricalFeatureOps == null) {
+ return null;
+ }
+ return mHistoricalFeatureOps.get(featureId);
+ }
+ }
+
+ /**
+ * This class represents historical app op information about a feature in a package.
+ *
+ * @hide
+ */
+ @TestApi
+ @SystemApi
+ /* codegen verifier cannot deal with nested class parameters
+ @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;
+
+ /** Ops for this feature */
+ private @Nullable ArrayMap<String, HistoricalOp> mHistoricalOps;
+
+ /** @hide */
+ public HistoricalFeatureOps(@NonNull String featureId) {
+ mFeatureId = featureId;
+ }
+
+ private HistoricalFeatureOps(@NonNull HistoricalFeatureOps other) {
+ mFeatureId = other.mFeatureId;
final int opCount = other.getOpCount();
for (int i = 0; i < opCount; i++) {
final HistoricalOp origOp = other.getOpAt(i);
@@ -4753,20 +5181,15 @@
}
}
- private HistoricalPackageOps(@NonNull Parcel parcel) {
- mPackageName = parcel.readString();
- mHistoricalOps = parcel.createTypedArrayMap(HistoricalOp.CREATOR);
- }
-
- private @Nullable HistoricalPackageOps splice(double fractionToRemove) {
- HistoricalPackageOps splice = null;
+ private @Nullable HistoricalFeatureOps splice(double fractionToRemove) {
+ HistoricalFeatureOps 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 HistoricalPackageOps(mPackageName);
+ splice = new HistoricalFeatureOps(mFeatureId, null);
}
if (splice.mHistoricalOps == null) {
splice.mHistoricalOps = new ArrayMap<>();
@@ -4777,7 +5200,7 @@
return splice;
}
- private void merge(@NonNull HistoricalPackageOps other) {
+ private void merge(@NonNull HistoricalFeatureOps other) {
final int opCount = other.getOpCount();
for (int i = 0; i < opCount; i++) {
final HistoricalOp otherOp = other.getOpAt(i);
@@ -4793,11 +5216,13 @@
}
}
- private void filter(@Nullable String[] opNames, double scaleFactor) {
+ private void filter(@Nullable String[] opNames, @HistoricalOpsRequestFilter int filter,
+ double scaleFactor) {
final int opCount = getOpCount();
for (int i = opCount - 1; i >= 0; i--) {
final HistoricalOp op = mHistoricalOps.valueAt(i);
- if (opNames != null && !ArrayUtils.contains(opNames, op.getOpName())) {
+ if ((filter & FILTER_BY_OP_NAMES) != 0 && !ArrayUtils.contains(opNames,
+ op.getOpName())) {
mHistoricalOps.removeAt(i);
} else {
op.filter(scaleFactor);
@@ -4832,15 +5257,6 @@
}
/**
- * Gets the package name which the data represents.
- *
- * @return The package name which the data represents.
- */
- public @NonNull String getPackageName() {
- return mPackageName;
- }
-
- /**
* Gets number historical app ops.
*
* @return The number historical app ops.
@@ -4880,19 +5296,8 @@
return mHistoricalOps.get(opName);
}
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel parcel, int flags) {
- parcel.writeString(mPackageName);
- parcel.writeTypedArrayMap(mHistoricalOps, flags);
- }
-
private void accept(@NonNull HistoricalOpsVisitor visitor) {
- visitor.visitHistoricalPackageOps(this);
+ visitor.visitHistoricalFeatureOps(this);
final int opCount = getOpCount();
for (int i = 0; i < opCount; i++) {
getOpAt(i).accept(visitor);
@@ -4912,47 +5317,143 @@
return op;
}
- public static final @android.annotation.NonNull Creator<HistoricalPackageOps> CREATOR =
- new Creator<HistoricalPackageOps>() {
+
+
+ // 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/app/AppOpsManager.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new HistoricalFeatureOps.
+ *
+ * @param featureId
+ * Id of the {@link Context#createFeatureContext feature} in the package
+ * @param historicalOps
+ * Ops for this feature
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public HistoricalFeatureOps(
+ @Nullable String featureId,
+ @Nullable ArrayMap<String,HistoricalOp> historicalOps) {
+ this.mFeatureId = featureId;
+ this.mHistoricalOps = historicalOps;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * Id of the {@link Context#createFeatureContext feature} in the package
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getFeatureId() {
+ return mFeatureId;
+ }
+
+ @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(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ HistoricalFeatureOps that = (HistoricalFeatureOps) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && Objects.equals(mFeatureId, that.mFeatureId)
+ && Objects.equals(mHistoricalOps, that.mHistoricalOps);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + Objects.hashCode(mFeatureId);
+ _hash = 31 * _hash + Objects.hashCode(mHistoricalOps);
+ return _hash;
+ }
+
+ @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) { ... }
+
+ byte flg = 0;
+ if (mFeatureId != null) flg |= 0x1;
+ if (mHistoricalOps != null) flg |= 0x2;
+ dest.writeByte(flg);
+ if (mFeatureId != null) dest.writeString(mFeatureId);
+ if (mHistoricalOps != null) dest.writeMap(mHistoricalOps);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ HistoricalFeatureOps(@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();
+ ArrayMap<String,HistoricalOp> historicalOps = null;
+ if ((flg & 0x2) != 0) {
+ historicalOps = new ArrayMap();
+ in.readMap(historicalOps, HistoricalOp.class.getClassLoader());
+ }
+
+ this.mFeatureId = featureId;
+ 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>() {
@Override
- public @NonNull HistoricalPackageOps createFromParcel(@NonNull Parcel parcel) {
- return new HistoricalPackageOps(parcel);
+ public HistoricalFeatureOps[] newArray(int size) {
+ return new HistoricalFeatureOps[size];
}
@Override
- public @NonNull HistoricalPackageOps[] newArray(int size) {
- return new HistoricalPackageOps[size];
+ public HistoricalFeatureOps createFromParcel(@NonNull Parcel in) {
+ return new HistoricalFeatureOps(in);
}
};
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
- final HistoricalPackageOps other = (HistoricalPackageOps) obj;
- if (!mPackageName.equals(other.mPackageName)) {
- return false;
- }
- if (mHistoricalOps == null) {
- if (other.mHistoricalOps != null) {
- return false;
- }
- } else if (!mHistoricalOps.equals(other.mHistoricalOps)) {
- return false;
- }
- return true;
- }
+ /*
+ @DataClass.Generated(
+ 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)")
+ @Deprecated
+ private void __metadata() {}
+ */
- @Override
- public int hashCode() {
- int result = mPackageName != null ? mPackageName.hashCode() : 0;
- result = 31 * result + (mHistoricalOps != null ? mHistoricalOps.hashCode() : 0);
- return result;
- }
+ //@formatter:on
+ // End of generated code
+
}
/**
@@ -5288,13 +5789,13 @@
if (mOp != other.mOp) {
return false;
}
- if (!Objects.equals(mAccessCount, other.mAccessCount)) {
+ if (!equalsLongSparseLongArray(mAccessCount, other.mAccessCount)) {
return false;
}
- if (!Objects.equals(mRejectCount, other.mRejectCount)) {
+ if (!equalsLongSparseLongArray(mRejectCount, other.mRejectCount)) {
return false;
}
- return Objects.equals(mAccessDuration, other.mAccessDuration);
+ return equalsLongSparseLongArray(mAccessDuration, other.mAccessDuration);
}
@Override
@@ -5621,9 +6122,9 @@
Objects.requireNonNull(executor, "executor cannot be null");
Objects.requireNonNull(callback, "callback cannot be null");
try {
- mService.getHistoricalOps(request.mUid, request.mPackageName, request.mOpNames,
- request.mBeginTimeMillis, request.mEndTimeMillis, request.mFlags,
- new RemoteCallback((result) -> {
+ mService.getHistoricalOps(request.mUid, request.mPackageName, request.mFeatureId,
+ 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 {
@@ -5661,8 +6162,8 @@
Objects.requireNonNull(callback, "callback cannot be null");
try {
mService.getHistoricalOpsFromDiskRaw(request.mUid, request.mPackageName,
- request.mOpNames, request.mBeginTimeMillis, request.mEndTimeMillis,
- request.mFlags, new RemoteCallback((result) -> {
+ request.mFeatureId, 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 {
@@ -7503,6 +8004,30 @@
return lastEvent;
}
+ private static boolean equalsLongSparseLongArray(@Nullable LongSparseLongArray a,
+ @Nullable LongSparseLongArray b) {
+ if (a == b) {
+ return true;
+ }
+
+ if (a == null || b == null) {
+ return false;
+ }
+
+ if (a.size() != b.size()) {
+ return false;
+ }
+
+ int numEntries = a.size();
+ for (int i = 0; i < numEntries; i++) {
+ if (a.keyAt(i) != b.keyAt(i) || a.valueAt(i) != b.valueAt(i)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
private static void writeLongSparseLongArrayToParcel(
@Nullable LongSparseLongArray array, @NonNull Parcel parcel) {
if (array != null) {
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index f0b87a8..91cf120 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -81,6 +81,7 @@
TAG_CRYPTO_SELF_TEST_COMPLETED,
TAG_KEY_INTEGRITY_VIOLATION,
TAG_CERT_VALIDATION_FAILURE,
+ TAG_CAMERA_POLICY_SET
})
public @interface SecurityLogTag {}
@@ -433,6 +434,19 @@
SecurityLogTags.SECURITY_CERT_VALIDATION_FAILURE;
/**
+ * Indicates that the admin has set policy to disable camera.
+ * The log entry contains the following information about the event, encapsulated in an
+ * {@link Object} array and accessible via {@link SecurityEvent#getData()}:
+ * <li> [0] admin package name ({@code String})
+ * <li> [1] admin user ID ({@code Integer})
+ * <li> [2] target user ID ({@code Integer})
+ * <li> [3] whether the camera is disabled or not ({@code Integer}, 1 if it's disabled,
+ * 0 if enabled)
+ */
+ public static final int TAG_CAMERA_POLICY_SET =
+ SecurityLogTags.SECURITY_CAMERA_POLICY_SET;
+
+ /**
* Event severity level indicating that the event corresponds to normal workflow.
*/
public static final int LEVEL_INFO = 1;
@@ -561,6 +575,7 @@
case TAG_MAX_PASSWORD_ATTEMPTS_SET:
case TAG_USER_RESTRICTION_ADDED:
case TAG_USER_RESTRICTION_REMOVED:
+ case TAG_CAMERA_POLICY_SET:
return LEVEL_INFO;
case TAG_CERT_AUTHORITY_REMOVED:
case TAG_CRYPTO_SELF_TEST_COMPLETED:
diff --git a/core/java/android/app/admin/SecurityLogTags.logtags b/core/java/android/app/admin/SecurityLogTags.logtags
index fe2519d..4e67fe2 100644
--- a/core/java/android/app/admin/SecurityLogTags.logtags
+++ b/core/java/android/app/admin/SecurityLogTags.logtags
@@ -38,3 +38,4 @@
210031 security_crypto_self_test_completed (success|1)
210032 security_key_integrity_violation (key_id|3),(uid|1)
210033 security_cert_validation_failure (reason|3)
+210034 security_camera_policy_set (package|3),(admin_user|1),(target_user|1),(disabled|1)
diff --git a/core/java/android/net/http/OWNERS b/core/java/android/net/http/OWNERS
index 6b8c9ed..3092612 100644
--- a/core/java/android/net/http/OWNERS
+++ b/core/java/android/net/http/OWNERS
@@ -1,3 +1,4 @@
-flooey@google.com
narayan@google.com
tobiast@google.com
+include platform/libcore:/OWNERS
+include platform/external/conscrypt:/OWNERS
diff --git a/core/java/android/os/ExternalVibration.java b/core/java/android/os/ExternalVibration.java
index 041d21f..e62244f 100644
--- a/core/java/android/os/ExternalVibration.java
+++ b/core/java/android/os/ExternalVibration.java
@@ -84,6 +84,10 @@
return mAttrs;
}
+ public VibrationAttributes getVibrationAttributes() {
+ return new VibrationAttributes.Builder(mAttrs, null).build();
+ }
+
/**
* Mutes the external vibration if it's playing and unmuted.
*
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index 6b881fe..7b2d148 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -16,17 +16,18 @@
package android.os;
-import android.media.AudioAttributes;
import android.os.VibrationEffect;
+import android.os.VibrationAttributes;
/** {@hide} */
interface IVibratorService
{
boolean hasVibrator();
boolean hasAmplitudeControl();
- boolean setAlwaysOnEffect(int id, in VibrationEffect effect, in AudioAttributes attributes);
- void vibrate(int uid, String opPkg, in VibrationEffect effect, in AudioAttributes attributes,
- String reason, IBinder token);
+ boolean setAlwaysOnEffect(int id, in VibrationEffect effect,
+ in VibrationAttributes attributes);
+ void vibrate(int uid, String opPkg, in VibrationEffect effect,
+ in VibrationAttributes attributes, String reason, IBinder token);
void cancelVibrate(IBinder token);
}
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index f585c75..c1542c7 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -76,7 +76,8 @@
return false;
}
try {
- return mService.setAlwaysOnEffect(id, effect, attributes);
+ VibrationAttributes atr = new VibrationAttributes.Builder(attributes, effect).build();
+ return mService.setAlwaysOnEffect(id, effect, atr);
} catch (RemoteException e) {
Log.w(TAG, "Failed to set always-on effect.", e);
}
@@ -91,7 +92,11 @@
return;
}
try {
- mService.vibrate(uid, opPkg, effect, attributes, reason, mToken);
+ if (attributes == null) {
+ attributes = new AudioAttributes.Builder().build();
+ }
+ VibrationAttributes atr = new VibrationAttributes.Builder(attributes, effect).build();
+ mService.vibrate(uid, opPkg, effect, atr, reason, mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
}
diff --git a/core/java/android/os/VibrationAttributes.aidl b/core/java/android/os/VibrationAttributes.aidl
new file mode 100644
index 0000000..5c05a4e
--- /dev/null
+++ b/core/java/android/os/VibrationAttributes.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.os;
+
+parcelable VibrationAttributes;
diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java
new file mode 100644
index 0000000..3e16640
--- /dev/null
+++ b/core/java/android/os/VibrationAttributes.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.media.AudioAttributes;
+import android.util.Slog;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * A class to encapsulate a collection of attributes describing information about a vibration
+ */
+public final class VibrationAttributes implements Parcelable {
+ private static final String TAG = "VibrationAttributes";
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = { "USAGE_CLASS_" }, value = {
+ USAGE_CLASS_UNKNOWN,
+ USAGE_CLASS_ALARM,
+ USAGE_CLASS_FEEDBACK,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UsageClass{}
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = { "USAGE_" }, value = {
+ USAGE_UNKNOWN,
+ USAGE_ALARM,
+ USAGE_RINGTONE,
+ USAGE_NOTIFICATION,
+ USAGE_COMMUNICATION_REQUEST,
+ USAGE_TOUCH,
+ USAGE_PHYSICAL_EMULATION,
+ USAGE_HARDWARE_FEEDBACK,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Usage{}
+
+ /**
+ * Vibration usage class value to use when the vibration usage class is unknown.
+ */
+ public static final int USAGE_CLASS_UNKNOWN = 0x0;
+ /**
+ * Vibration usage class value to use when the vibration is initiated to catch user's
+ * attention, such as alarm, ringtone, and notification vibrations.
+ */
+ public static final int USAGE_CLASS_ALARM = 0x1;
+ /**
+ * Vibration usage class value to use when the vibration is initiated as a response to user's
+ * actions, such as emulation of physical effects, and texting feedback vibration.
+ */
+ public static final int USAGE_CLASS_FEEDBACK = 0x2;
+
+ /**
+ * Mask for vibration usage class value.
+ */
+ public static final int USAGE_CLASS_MASK = 0xF;
+
+ /**
+ * Usage value to use when usage is unknown.
+ */
+ public static final int USAGE_UNKNOWN = 0x0 | USAGE_CLASS_UNKNOWN;
+ /**
+ * Usage value to use for alarm vibrations.
+ */
+ public static final int USAGE_ALARM = 0x10 | USAGE_CLASS_ALARM;
+ /**
+ * Usage value to use for ringtone vibrations.
+ */
+ public static final int USAGE_RINGTONE = 0x20 | USAGE_CLASS_ALARM;
+ /**
+ * Usage value to use for notification vibrations.
+ */
+ public static final int USAGE_NOTIFICATION = 0x30 | USAGE_CLASS_ALARM;
+ /**
+ * Usage value to use for vibrations which mean a request to enter/end a
+ * communication, such as a VoIP communication or video-conference.
+ */
+ public static final int USAGE_COMMUNICATION_REQUEST = 0x40 | USAGE_CLASS_ALARM;
+ /**
+ * Usage value to use for touch vibrations.
+ */
+ public static final int USAGE_TOUCH = 0x10 | USAGE_CLASS_FEEDBACK;
+ /**
+ * Usage value to use for vibrations which emulate physical effects, such as edge squeeze.
+ */
+ public static final int USAGE_PHYSICAL_EMULATION = 0x20 | USAGE_CLASS_FEEDBACK;
+ /**
+ * Usage value to use for vibrations which provide a feedback for hardware interaction,
+ * such as a fingerprint sensor.
+ */
+ public static final int USAGE_HARDWARE_FEEDBACK = 0x30 | USAGE_CLASS_FEEDBACK;
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = { "FLAG_" }, value = {
+ FLAG_BYPASS_INTERRUPTION_POLICY,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Flag{}
+
+ /**
+ * Flag requesting vibration effect to be played even under limited interruptions.
+ */
+ public static final int FLAG_BYPASS_INTERRUPTION_POLICY = 0x1;
+
+ // If a vibration is playing for longer than 5s, it's probably not haptic feedback
+ private static final long MAX_HAPTIC_FEEDBACK_DURATION = 5000;
+
+ private final int mUsage;
+ private final int mFlags;
+
+ private final AudioAttributes mAudioAttributes;
+
+ private VibrationAttributes(int usage, int flags, @NonNull AudioAttributes audio) {
+ mUsage = usage;
+ mFlags = flags;
+ mAudioAttributes = audio;
+ }
+
+ /**
+ * Return the vibration usage class.
+ * @return USAGE_CLASS_ALARM, USAGE_CLASS_FEEDBACK or USAGE_CLASS_UNKNOWN
+ */
+ public int getUsageClass() {
+ return mUsage & USAGE_CLASS_MASK;
+ }
+
+ /**
+ * Return the vibration usage.
+ * @return one of the values that can be set in {@link Builder#setUsage(int)}
+ */
+ public int getUsage() {
+ return mUsage;
+ }
+
+ /**
+ * Return the flags.
+ * @return a combined mask of all flags
+ */
+ public int getFlags() {
+ return mFlags;
+ }
+
+ /**
+ * Check whether a flag is set
+ * @return true if a flag is set and false otherwise
+ */
+ public boolean isFlagSet(int flag) {
+ return (mFlags & flag) > 0;
+ }
+
+ /**
+ * Return AudioAttributes equivalent to this VibrationAttributes.
+ * @deprecated Temporary support of AudioAttributes, will be removed when out of WIP
+ * @hide
+ */
+ @Deprecated
+ @TestApi
+ public @NonNull AudioAttributes getAudioAttributes() {
+ return mAudioAttributes;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mUsage);
+ dest.writeInt(mFlags);
+ dest.writeParcelable(mAudioAttributes, flags);
+ }
+
+ private VibrationAttributes(Parcel src) {
+ mUsage = src.readInt();
+ mFlags = src.readInt();
+ mAudioAttributes = (AudioAttributes) src.readParcelable(
+ AudioAttributes.class.getClassLoader());
+ }
+
+ public static final @NonNull Parcelable.Creator<VibrationAttributes>
+ CREATOR = new Parcelable.Creator<VibrationAttributes>() {
+ public VibrationAttributes createFromParcel(Parcel p) {
+ return new VibrationAttributes(p);
+ }
+ public VibrationAttributes[] newArray(int size) {
+ return new VibrationAttributes[size];
+ }
+ };
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ VibrationAttributes rhs = (VibrationAttributes) o;
+ return mUsage == rhs.mUsage && mFlags == rhs.mFlags;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mUsage, mFlags);
+ }
+
+ @Override
+ public String toString() {
+ return "VibrationAttributes:"
+ + " Usage=" + usageToString()
+ + " Flags=" + mFlags;
+ }
+
+ /** @hide */
+ public String usageToString() {
+ return usageToString(mUsage);
+ }
+
+ /** @hide */
+ public String usageToString(int usage) {
+ switch (usage) {
+ case USAGE_UNKNOWN:
+ return "UNKNOWN";
+ case USAGE_ALARM:
+ return "ALARM";
+ case USAGE_RINGTONE:
+ return "RIGNTONE";
+ case USAGE_NOTIFICATION:
+ return "NOTIFICATION";
+ case USAGE_COMMUNICATION_REQUEST:
+ return "COMMUNICATION_REQUEST";
+ case USAGE_TOUCH:
+ return "TOUCH";
+ case USAGE_PHYSICAL_EMULATION:
+ return "PHYSICAL_EMULATION";
+ case USAGE_HARDWARE_FEEDBACK:
+ return "HARDWARE_FEEDBACK";
+ default:
+ return "unknown usage " + usage;
+ }
+ }
+
+ /**
+ * Builder class for {@link VibrationAttributes} objects.
+ * By default, all information is set to UNKNOWN.
+ */
+ public static final class Builder {
+ private int mUsage = USAGE_UNKNOWN;
+ private int mFlags = 0x0;
+
+ private AudioAttributes mAudioAttributes = new AudioAttributes.Builder().build();
+
+ /**
+ * Constructs a new Builder with the defaults.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Constructs a new Builder from a given VibrationAttributes.
+ */
+ public Builder(@Nullable VibrationAttributes vib) {
+ if (vib != null) {
+ mUsage = vib.mUsage;
+ mFlags = vib.mFlags;
+ mAudioAttributes = vib.mAudioAttributes;
+ }
+ }
+
+ /**
+ * Constructs a new Builder from AudioAttributes.
+ * @hide
+ */
+ @TestApi
+ public Builder(@NonNull AudioAttributes audio,
+ @Nullable VibrationEffect effect) {
+ mAudioAttributes = audio;
+ setUsage(audio);
+ applyHapticFeedbackHeuristics(effect);
+ }
+
+ private void applyHapticFeedbackHeuristics(@Nullable VibrationEffect effect) {
+ if (effect != null) {
+ if (mUsage == USAGE_UNKNOWN && effect instanceof VibrationEffect.Prebaked) {
+ VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) effect;
+ switch (prebaked.getId()) {
+ case VibrationEffect.EFFECT_CLICK:
+ case VibrationEffect.EFFECT_DOUBLE_CLICK:
+ case VibrationEffect.EFFECT_HEAVY_CLICK:
+ case VibrationEffect.EFFECT_TEXTURE_TICK:
+ case VibrationEffect.EFFECT_TICK:
+ case VibrationEffect.EFFECT_POP:
+ case VibrationEffect.EFFECT_THUD:
+ mUsage = USAGE_TOUCH;
+ break;
+ default:
+ Slog.w(TAG, "Unknown prebaked vibration effect, assuming it isn't "
+ + "haptic feedback");
+ }
+ }
+ final long duration = effect.getDuration();
+ if (mUsage == USAGE_UNKNOWN && duration >= 0
+ && duration < MAX_HAPTIC_FEEDBACK_DURATION) {
+ mUsage = USAGE_TOUCH;
+ }
+ }
+ }
+
+ private void setUsage(@NonNull AudioAttributes audio) {
+ switch (audio.getUsage()) {
+ case AudioAttributes.USAGE_NOTIFICATION:
+ case AudioAttributes.USAGE_NOTIFICATION_EVENT:
+ case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+ case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+ mUsage = USAGE_NOTIFICATION;
+ break;
+ case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+ case AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY:
+ mUsage = USAGE_COMMUNICATION_REQUEST;
+ break;
+ case AudioAttributes.USAGE_NOTIFICATION_RINGTONE:
+ mUsage = USAGE_RINGTONE;
+ break;
+ case AudioAttributes.USAGE_ASSISTANCE_SONIFICATION:
+ mUsage = USAGE_TOUCH;
+ break;
+ case AudioAttributes.USAGE_ALARM:
+ mUsage = USAGE_ALARM;
+ break;
+ default:
+ mUsage = USAGE_UNKNOWN;
+ }
+ }
+
+ /**
+ * Combines all of the attributes that have been set and returns a new
+ * {@link VibrationAttributes} object.
+ * @return a new {@link VibrationAttributes} object
+ */
+ public @NonNull VibrationAttributes build() {
+ VibrationAttributes ans = new VibrationAttributes(mUsage, mFlags,
+ mAudioAttributes);
+ return ans;
+ }
+
+ /**
+ * Sets the attribute describing the type of corresponding vibration.
+ * @param usage one of {@link VibrationAttributes#USAGE_ALARM},
+ * {@link VibrationAttributes#USAGE_RINGTONE},
+ * {@link VibrationAttributes#USAGE_NOTIFICATION},
+ * {@link VibrationAttributes#USAGE_COMMUNICATION_REQUEST},
+ * {@link VibrationAttributes#USAGE_TOUCH},
+ * {@link VibrationAttributes#USAGE_PHYSICAL_EMULATION},
+ * {@link VibrationAttributes#USAGE_HARDWARE_FEEDBACK}.
+ * @return the same Builder instance.
+ */
+ public @NonNull Builder setUsage(int usage) {
+ mUsage = usage;
+ return this;
+ }
+
+ /**
+ * Replaces flags
+ * @param flags any combination of flags.
+ * @return the same Builder instance.
+ */
+ public @NonNull Builder replaceFlags(int flags) {
+ mFlags = flags;
+ return this;
+ }
+ }
+}
+
diff --git a/core/java/android/provider/ContactsInternal.java b/core/java/android/provider/ContactsInternal.java
index 69c4b9b..aa2a89c 100644
--- a/core/java/android/provider/ContactsInternal.java
+++ b/core/java/android/provider/ContactsInternal.java
@@ -15,15 +15,14 @@
*/
package android.provider;
-import android.annotation.UnsupportedAppUsage;
import android.app.admin.DevicePolicyManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.UriMatcher;
import android.net.Uri;
-import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
import android.widget.Toast;
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index eb09930..0a3c333 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -22,7 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentInterface;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 9a384c6..48410a7 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -16,8 +16,8 @@
package android.provider;
-import android.annotation.UnsupportedAppUsage;
import android.app.DownloadManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.NetworkPolicyManager;
import android.net.Uri;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 3aa534e..bbaf94a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -26,7 +26,6 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.app.ActivityThread;
import android.app.AppOpsManager;
@@ -36,6 +35,7 @@
import android.app.NotificationManager;
import android.app.SearchManager;
import android.app.WallpaperManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -252,6 +252,9 @@
/** @hide */
public static final String EXTRA_NETWORK_TEMPLATE = "network_template";
+ /** @hide */
+ public static final String KEY_CONFIG_SET_RETURN = "config_set_return";
+
/**
* An int extra specifying a subscription ID.
*
@@ -2504,13 +2507,14 @@
args.putString(CALL_METHOD_PREFIX_KEY, prefix);
args.putSerializable(CALL_METHOD_FLAGS_KEY, keyValues);
IContentProvider cp = mProviderHolder.getProvider(cr);
- cp.call(cr.getPackageName(), cr.getFeatureId(), mProviderHolder.mUri.getAuthority(),
+ Bundle bundle = cp.call(cr.getPackageName(), cr.getFeatureId(),
+ mProviderHolder.mUri.getAuthority(),
mCallSetAllCommand, null, args);
+ return bundle.getBoolean(KEY_CONFIG_SET_RETURN);
} catch (RemoteException e) {
// Not supported by the remote side
return false;
}
- return true;
}
@UnsupportedAppUsage
@@ -13709,14 +13713,6 @@
"backup_agent_timeout_parameters";
/**
- * Whether the backup system service supports multiple users (0 = disabled, 1 = enabled). If
- * disabled, the service will only be active for the system user.
- *
- * @hide
- */
- public static final String BACKUP_MULTI_USER_ENABLED = "backup_multi_user_enabled";
-
- /**
* Blacklist of GNSS satellites.
*
* This is a list of integers separated by commas to represent pairs of (constellation,
@@ -13985,14 +13981,18 @@
*/
@RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
static boolean setStrings(@NonNull ContentResolver resolver, @NonNull String namespace,
- @NonNull Map<String, String> keyValues) {
+ @NonNull Map<String, String> keyValues) throws DeviceConfig.BadConfigException {
HashMap<String, String> compositeKeyValueMap = new HashMap<>(keyValues.keySet().size());
for (Map.Entry<String, String> entry : keyValues.entrySet()) {
compositeKeyValueMap.put(
createCompositeName(namespace, entry.getKey()), entry.getValue());
}
- return sNameValueCache.setStringsForPrefix(resolver, createPrefix(namespace),
- compositeKeyValueMap);
+ // If can't set given configuration that means it's bad
+ if (!sNameValueCache.setStringsForPrefix(resolver, createPrefix(namespace),
+ compositeKeyValueMap)) {
+ throw new DeviceConfig.BadConfigException();
+ }
+ return true;
}
/**
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 2aa346c..1d9bdb8 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -24,8 +24,8 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.compat.annotation.ChangeId;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -4216,7 +4216,7 @@
* The subscription which received this cell broadcast message.
* <P>Type: INTEGER</P>
*/
- public static final String SUB_ID = "sub_id";
+ public static final String SUBSCRIPTION_ID = "sub_id";
/**
* The slot which received this cell broadcast message.
@@ -4474,7 +4474,7 @@
public static final String[] QUERY_COLUMNS_FWK = {
_ID,
SLOT_INDEX,
- SUB_ID,
+ SUBSCRIPTION_ID,
GEOGRAPHICAL_SCOPE,
PLMN,
LAC,
diff --git a/core/java/android/security/KeystoreArguments.java b/core/java/android/security/KeystoreArguments.java
index e634234..a59c4e0 100644
--- a/core/java/android/security/KeystoreArguments.java
+++ b/core/java/android/security/KeystoreArguments.java
@@ -16,7 +16,7 @@
package android.security;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/security/keymaster/ExportResult.java b/core/java/android/security/keymaster/ExportResult.java
index 1be5ae9..037b852 100644
--- a/core/java/android/security/keymaster/ExportResult.java
+++ b/core/java/android/security/keymaster/ExportResult.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java
index 2eb2cef..d8382fa 100644
--- a/core/java/android/security/keymaster/KeyCharacteristics.java
+++ b/core/java/android/security/keymaster/KeyCharacteristics.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/security/keymaster/KeymasterArguments.java b/core/java/android/security/keymaster/KeymasterArguments.java
index d2dbdec..e009e12 100644
--- a/core/java/android/security/keymaster/KeymasterArguments.java
+++ b/core/java/android/security/keymaster/KeymasterArguments.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/security/keymaster/KeymasterBlob.java b/core/java/android/security/keymaster/KeymasterBlob.java
index 6a2024f..68365bf 100644
--- a/core/java/android/security/keymaster/KeymasterBlob.java
+++ b/core/java/android/security/keymaster/KeymasterBlob.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/security/keymaster/KeymasterBlobArgument.java b/core/java/android/security/keymaster/KeymasterBlobArgument.java
index fc562bd..81b08c5 100644
--- a/core/java/android/security/keymaster/KeymasterBlobArgument.java
+++ b/core/java/android/security/keymaster/KeymasterBlobArgument.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
/**
diff --git a/core/java/android/security/keymaster/KeymasterBooleanArgument.java b/core/java/android/security/keymaster/KeymasterBooleanArgument.java
index 4286aa0..25b2ac4 100644
--- a/core/java/android/security/keymaster/KeymasterBooleanArgument.java
+++ b/core/java/android/security/keymaster/KeymasterBooleanArgument.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
/**
diff --git a/core/java/android/security/keymaster/KeymasterDateArgument.java b/core/java/android/security/keymaster/KeymasterDateArgument.java
index 3e04c15..218f488 100644
--- a/core/java/android/security/keymaster/KeymasterDateArgument.java
+++ b/core/java/android/security/keymaster/KeymasterDateArgument.java
@@ -16,8 +16,9 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
+
import java.util.Date;
/**
diff --git a/core/java/android/security/keymaster/KeymasterIntArgument.java b/core/java/android/security/keymaster/KeymasterIntArgument.java
index 4aadce4..01d38c7 100644
--- a/core/java/android/security/keymaster/KeymasterIntArgument.java
+++ b/core/java/android/security/keymaster/KeymasterIntArgument.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
/**
diff --git a/core/java/android/security/keymaster/KeymasterLongArgument.java b/core/java/android/security/keymaster/KeymasterLongArgument.java
index bc2255e..3ac27cc 100644
--- a/core/java/android/security/keymaster/KeymasterLongArgument.java
+++ b/core/java/android/security/keymaster/KeymasterLongArgument.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
/**
diff --git a/core/java/android/security/keymaster/OperationResult.java b/core/java/android/security/keymaster/OperationResult.java
index c278eb3..b4e155a 100644
--- a/core/java/android/security/keymaster/OperationResult.java
+++ b/core/java/android/security/keymaster/OperationResult.java
@@ -16,7 +16,7 @@
package android.security.keymaster;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/security/net/config/RootTrustManager.java b/core/java/android/security/net/config/RootTrustManager.java
index d8936d9..58dc4ba 100644
--- a/core/java/android/security/net/config/RootTrustManager.java
+++ b/core/java/android/security/net/config/RootTrustManager.java
@@ -16,15 +16,16 @@
package android.security.net.config;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.net.Socket;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;
-import android.annotation.UnsupportedAppUsage;
-import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
import javax.net.ssl.X509ExtendedTrustManager;
/**
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 38de794..de4a551 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -21,9 +21,9 @@
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.UnsupportedAppUsage;
import android.app.AlarmManager;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.drawable.ColorDrawable;
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index c04ac59..80d054b 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -22,7 +22,6 @@
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.INotificationManager;
import android.app.Notification;
@@ -33,6 +32,7 @@
import android.app.Person;
import android.app.Service;
import android.companion.CompanionDeviceManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index b8378a3..389040c 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -17,11 +17,10 @@
package android.service.notification;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Person;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index dedc3b7..3f9462c 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -20,11 +20,11 @@
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index cf56eae..67925bf 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 0de17ca..36e057f 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -18,8 +18,8 @@
import android.annotation.NonNull;
import android.annotation.SdkConstant;
-import android.annotation.UnsupportedAppUsage;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/service/vr/VrListenerService.java b/core/java/android/service/vr/VrListenerService.java
index 3c38495..2758ace 100644
--- a/core/java/android/service/vr/VrListenerService.java
+++ b/core/java/android/service/vr/VrListenerService.java
@@ -18,9 +18,9 @@
import android.annotation.NonNull;
import android.annotation.SdkConstant;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/core/java/android/service/wallpaper/Android.bp b/core/java/android/service/wallpaper/Android.bp
index aa6123f..ffbdb03 100644
--- a/core/java/android/service/wallpaper/Android.bp
+++ b/core/java/android/service/wallpaper/Android.bp
@@ -6,6 +6,8 @@
"I*.aidl",
],
+ libs: ["unsupportedappusage"],
+
// Enforce that the library is built against java 8 so that there are
// no compatibility issues with launcher
java_version: "1.8",
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index e50d6c2..9a76a1b 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -20,11 +20,11 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.Service;
import android.app.WallpaperColors;
import android.app.WallpaperInfo;
import android.app.WallpaperManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 172495f..c861fa7 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -21,7 +21,7 @@
import android.annotation.RawRes;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/core/java/android/speech/tts/TtsEngines.java b/core/java/android/speech/tts/TtsEngines.java
index 2fab404..a8aea7c 100644
--- a/core/java/android/speech/tts/TtsEngines.java
+++ b/core/java/android/speech/tts/TtsEngines.java
@@ -18,7 +18,7 @@
import static android.provider.Settings.Secure.getString;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 7841f99..e08a06a 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -21,7 +21,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
@@ -369,6 +369,21 @@
@RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 0x20000000;
+ /**
+ * Listen for Registration Failures.
+ *
+ * Listen for indications that a registration procedure has failed in either the CS or PS
+ * domain. This indication does not necessarily indicate a change of service state, which should
+ * be tracked via {@link #LISTEN_SERVICE_STATE}.
+ *
+ * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
+ * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
+ *
+ * @see #onRegistrationFailed()
+ */
+ @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
+ public static final int LISTEN_REGISTRATION_FAILURE = 0x40000000;
+
/*
* Subscription used to listen to the phone state changes
* @hide
@@ -932,6 +947,38 @@
}
/**
+ * Report that Registration or a Location/Routing/Tracking Area update has failed.
+ *
+ * <p>Indicate whenever a registration procedure, including a location, routing, or tracking
+ * area update fails. This includes procedures that do not necessarily result in a change of
+ * the modem's registration status. If the modem's registration status changes, that is
+ * reflected in the onNetworkStateChanged() and subsequent get{Voice/Data}RegistrationState().
+ *
+ * <p>Because registration failures are ephemeral, this callback is not sticky.
+ * Registrants will not receive the most recent past value when registering.
+ *
+ * @param cellIdentity the CellIdentity, which must include the globally unique identifier
+ * for the cell (for example, all components of the CGI or ECGI).
+ * @param chosenPlmn a 5 or 6 digit alphanumeric PLMN (MCC|MNC) among those broadcast by the
+ * cell that was chosen for the failed registration attempt.
+ * @param domain DOMAIN_CS, DOMAIN_PS or both in case of a combined procedure.
+ * @param causeCode the primary failure cause code of the procedure.
+ * For GSM/UMTS (MM), values are in TS 24.008 Sec 10.5.95
+ * For GSM/UMTS (GMM), values are in TS 24.008 Sec 10.5.147
+ * For LTE (EMM), cause codes are TS 24.301 Sec 9.9.3.9
+ * For NR (5GMM), cause codes are TS 24.501 Sec 9.11.3.2
+ * Integer.MAX_VALUE if this value is unused.
+ * @param additionalCauseCode the cause code of any secondary/combined procedure if appropriate.
+ * For UMTS, if a combined attach succeeds for PS only, then the GMM cause code shall be
+ * included as an additionalCauseCode. For LTE (ESM), cause codes are in
+ * TS 24.301 9.9.4.4. Integer.MAX_VALUE if this value is unused.
+ */
+ public void onRegistrationFailed(@NonNull CellIdentity cellIdentity, @NonNull String chosenPlmn,
+ @NetworkRegistrationInfo.Domain int domain, int causeCode, int additionalCauseCode) {
+ // default implementation empty
+ }
+
+ /**
* The callback methods need to be called on the handler thread where
* this object was created. If the binder did that for us it'd be nice.
*
@@ -1203,6 +1250,18 @@
() -> psl.onImsCallDisconnectCauseChanged(disconnectCause)));
}
+
+ public void onRegistrationFailed(@NonNull CellIdentity cellIdentity,
+ @NonNull String chosenPlmn, @NetworkRegistrationInfo.Domain int domain,
+ int causeCode, int additionalCauseCode) {
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onRegistrationFailed(
+ cellIdentity, chosenPlmn, domain, causeCode, additionalCauseCode)));
+ // default implementation empty
+ }
}
diff --git a/core/java/android/telephony/Rlog.java b/core/java/android/telephony/Rlog.java
index cdab2dc..2afdd33 100644
--- a/core/java/android/telephony/Rlog.java
+++ b/core/java/android/telephony/Rlog.java
@@ -16,12 +16,11 @@
package android.telephony;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.text.TextUtils;
-import android.util.Log;
-
-import android.annotation.UnsupportedAppUsage;
import android.util.Base64;
+import android.util.Log;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 1b2feda..b94475a 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -614,9 +614,9 @@
* Notify call disconnect causes which contains {@link DisconnectCause} and {@link
* android.telephony.PreciseDisconnectCause}.
*
- * @param subId for which call disconnected.
* @param slotIndex for which call disconnected. Can be derived from subId except when subId is
* invalid.
+ * @param subId for which call disconnected.
* @param cause {@link DisconnectCause} for the disconnected call.
* @param preciseCause {@link android.telephony.PreciseDisconnectCause} for the disconnected
* call.
@@ -675,4 +675,36 @@
}
}
+
+ /**
+ * Report that Registration or a Location/Routing/Tracking Area update has failed.
+ *
+ * @param slotIndex for which call disconnected. Can be derived from subId except when subId is
+ * invalid.
+ * @param subId for which cellinfo changed.
+ * @param cellIdentity the CellIdentity, which must include the globally unique identifier
+ * for the cell (for example, all components of the CGI or ECGI).
+ * @param chosenPlmn a 5 or 6 digit alphanumeric PLMN (MCC|MNC) among those broadcast by the
+ * cell that was chosen for the failed registration attempt.
+ * @param domain DOMAIN_CS, DOMAIN_PS or both in case of a combined procedure.
+ * @param causeCode the primary failure cause code of the procedure.
+ * For GSM/UMTS (MM), values are in TS 24.008 Sec 10.5.95
+ * For GSM/UMTS (GMM), values are in TS 24.008 Sec 10.5.147
+ * For LTE (EMM), cause codes are TS 24.301 Sec 9.9.3.9
+ * For NR (5GMM), cause codes are TS 24.501 Sec 9.11.3.2
+ * Integer.MAX_VALUE if this value is unused.
+ * @param additionalCauseCode the cause code of any secondary/combined procedure if appropriate.
+ * For UMTS, if a combined attach succeeds for PS only, then the GMM cause code shall be
+ * included as an additionalCauseCode. For LTE (ESM), cause codes are in
+ * TS 24.301 9.9.4.4. Integer.MAX_VALUE if this value is unused.
+ */
+ public void notifyRegistrationFailed(int slotIndex, int subId,
+ @NonNull CellIdentity cellIdentity, @NonNull String chosenPlmn,
+ @NetworkRegistrationInfo.Domain int domain, int causeCode, int additionalCauseCode) {
+ try {
+ sRegistry.notifyRegistrationFailed(slotIndex, subId, cellIdentity,
+ chosenPlmn, domain, causeCode, additionalCauseCode);
+ } catch (RemoteException ex) {
+ }
+ }
}
diff --git a/core/java/android/text/AndroidBidi.java b/core/java/android/text/AndroidBidi.java
index bb7fb44..f1e2181 100644
--- a/core/java/android/text/AndroidBidi.java
+++ b/core/java/android/text/AndroidBidi.java
@@ -16,7 +16,7 @@
package android.text;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.icu.lang.UCharacter;
import android.icu.lang.UCharacterDirection;
import android.icu.lang.UProperty;
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index cf6987c..3ee1a90 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -16,7 +16,7 @@
package android.text;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 32982f9..c60d446 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -20,7 +20,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index 19c55d5..b5688a4 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -21,7 +21,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.fonts.FontVariationAxis;
import android.net.Uri;
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index 18f8db2..55af087 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -16,9 +16,9 @@
package android.text;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.Application;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Typeface;
diff --git a/core/java/android/text/InputFilter.java b/core/java/android/text/InputFilter.java
index a9a7b2f..96e7bd0 100644
--- a/core/java/android/text/InputFilter.java
+++ b/core/java/android/text/InputFilter.java
@@ -17,7 +17,7 @@
package android.text;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.Preconditions;
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 2c2c295..8a4497a 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -18,7 +18,7 @@
import android.annotation.IntDef;
import android.annotation.IntRange;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
index 68199a4..57c1d23 100644
--- a/core/java/android/text/Selection.java
+++ b/core/java/android/text/Selection.java
@@ -17,7 +17,7 @@
package android.text;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.text.BreakIterator;
diff --git a/core/java/android/text/SpanSet.java b/core/java/android/text/SpanSet.java
index 362825a..81bdd65 100644
--- a/core/java/android/text/SpanSet.java
+++ b/core/java/android/text/SpanSet.java
@@ -16,7 +16,8 @@
package android.text;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.lang.reflect.Array;
import java.util.Arrays;
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 0d29da0..ac27e3d 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -17,7 +17,7 @@
package android.text;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.BaseCanvas;
import android.graphics.Paint;
import android.util.Log;
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index a986633..b85ef76 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -16,7 +16,7 @@
package android.text;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 69cfc03..85e2d98 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -20,7 +20,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Paint;
import android.graphics.text.LineBreaker;
import android.os.Build;
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 1c50d73..3c51fa7 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -19,7 +19,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
diff --git a/core/java/android/text/TextPaint.java b/core/java/android/text/TextPaint.java
index d5aad33..73825b1 100644
--- a/core/java/android/text/TextPaint.java
+++ b/core/java/android/text/TextPaint.java
@@ -18,7 +18,7 @@
import android.annotation.ColorInt;
import android.annotation.Px;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Paint;
/**
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 5bda867..df4ead1 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -24,7 +24,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.PluralsRes;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.icu.lang.UCharacter;
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 3c8de94..0863a81 100755
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -17,9 +17,8 @@
package android.text.format;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.os.UserHandle;
import android.provider.Settings;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 0c27923..ce676e0 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -16,7 +16,7 @@
package android.text.format;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index d7baa10..17d3ae4 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.icu.text.MeasureFormat;
diff --git a/core/java/android/text/method/AllCapsTransformationMethod.java b/core/java/android/text/method/AllCapsTransformationMethod.java
index 5a7c98d..305b056 100644
--- a/core/java/android/text/method/AllCapsTransformationMethod.java
+++ b/core/java/android/text/method/AllCapsTransformationMethod.java
@@ -17,7 +17,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Rect;
import android.text.Spanned;
diff --git a/core/java/android/text/method/HideReturnsTransformationMethod.java b/core/java/android/text/method/HideReturnsTransformationMethod.java
index 440a4b1..40ce871 100644
--- a/core/java/android/text/method/HideReturnsTransformationMethod.java
+++ b/core/java/android/text/method/HideReturnsTransformationMethod.java
@@ -16,7 +16,7 @@
package android.text.method;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
/**
diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java
index a0c44a8..c544c41 100644
--- a/core/java/android/text/method/LinkMovementMethod.java
+++ b/core/java/android/text/method/LinkMovementMethod.java
@@ -16,7 +16,7 @@
package android.text.method;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.text.Layout;
import android.text.NoCopySpan;
diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java
index ec7ed34b..d1d7c96 100644
--- a/core/java/android/text/method/MetaKeyKeyListener.java
+++ b/core/java/android/text/method/MetaKeyKeyListener.java
@@ -16,7 +16,7 @@
package android.text.method;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.text.Editable;
import android.text.NoCopySpan;
import android.text.Spannable;
diff --git a/core/java/android/text/method/PasswordTransformationMethod.java b/core/java/android/text/method/PasswordTransformationMethod.java
index c96fc5d..53553be 100644
--- a/core/java/android/text/method/PasswordTransformationMethod.java
+++ b/core/java/android/text/method/PasswordTransformationMethod.java
@@ -16,7 +16,7 @@
package android.text.method;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
diff --git a/core/java/android/text/method/TransformationMethod2.java b/core/java/android/text/method/TransformationMethod2.java
index 0bf401a..8d5ec24 100644
--- a/core/java/android/text/method/TransformationMethod2.java
+++ b/core/java/android/text/method/TransformationMethod2.java
@@ -15,7 +15,7 @@
*/
package android.text.method;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* TransformationMethod2 extends the TransformationMethod interface
diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java
index 313567a..d766186 100644
--- a/core/java/android/text/method/WordIterator.java
+++ b/core/java/android/text/method/WordIterator.java
@@ -17,7 +17,7 @@
package android.text.method;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.icu.lang.UCharacter;
import android.icu.lang.UProperty;
import android.icu.text.BreakIterator;
diff --git a/core/java/android/text/style/BulletSpan.java b/core/java/android/text/style/BulletSpan.java
index 9b1dfbf..ad61788 100644
--- a/core/java/android/text/style/BulletSpan.java
+++ b/core/java/android/text/style/BulletSpan.java
@@ -21,7 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Px;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Build;
diff --git a/core/java/android/text/style/DynamicDrawableSpan.java b/core/java/android/text/style/DynamicDrawableSpan.java
index 1a508a1..f37e423 100644
--- a/core/java/android/text/style/DynamicDrawableSpan.java
+++ b/core/java/android/text/style/DynamicDrawableSpan.java
@@ -22,7 +22,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
diff --git a/core/java/android/text/style/EasyEditSpan.java b/core/java/android/text/style/EasyEditSpan.java
index bfb2873..b23c2b7 100644
--- a/core/java/android/text/style/EasyEditSpan.java
+++ b/core/java/android/text/style/EasyEditSpan.java
@@ -17,8 +17,8 @@
package android.text.style;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextUtils;
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
index 98f58be..ec55aeb 100644
--- a/core/java/android/text/style/ImageSpan.java
+++ b/core/java/android/text/style/ImageSpan.java
@@ -19,7 +19,7 @@
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
diff --git a/core/java/android/text/style/SpellCheckSpan.java b/core/java/android/text/style/SpellCheckSpan.java
index 6ffde38..e8ec3c6 100644
--- a/core/java/android/text/style/SpellCheckSpan.java
+++ b/core/java/android/text/style/SpellCheckSpan.java
@@ -16,7 +16,7 @@
package android.text.style;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextUtils;
diff --git a/core/java/android/text/style/SuggestionRangeSpan.java b/core/java/android/text/style/SuggestionRangeSpan.java
index d958dde..2b04a7a 100644
--- a/core/java/android/text/style/SuggestionRangeSpan.java
+++ b/core/java/android/text/style/SuggestionRangeSpan.java
@@ -16,7 +16,7 @@
package android.text.style;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextPaint;
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index c000ae3..be01bfb 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -19,7 +19,7 @@
import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index 993bbe8..2aca36a 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index de182da..59a05ac 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -22,7 +22,7 @@
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.RectEvaluator;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
diff --git a/core/java/android/transition/Scene.java b/core/java/android/transition/Scene.java
index 8d4db54..52a97e3 100644
--- a/core/java/android/transition/Scene.java
+++ b/core/java/android/transition/Scene.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
import android.util.SparseArray;
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 0feab4d..e511584 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -20,7 +20,7 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Path;
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 0e5252e..1b0612e 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -17,7 +17,7 @@
package android.transition;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.ArrayMap;
import android.util.Log;
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index 3f44e48..4cf0a36 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.ArrayUtils;
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index 4dda709..7f652ba 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -18,7 +18,7 @@
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import libcore.util.EmptyArray;
diff --git a/core/java/android/util/Base64.java b/core/java/android/util/Base64.java
index ecc0c9c..92abd7c 100644
--- a/core/java/android/util/Base64.java
+++ b/core/java/android/util/Base64.java
@@ -16,7 +16,8 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.UnsupportedEncodingException;
/**
diff --git a/core/java/android/util/Base64OutputStream.java b/core/java/android/util/Base64OutputStream.java
index 230a3a5..48fadeb 100644
--- a/core/java/android/util/Base64OutputStream.java
+++ b/core/java/android/util/Base64OutputStream.java
@@ -16,7 +16,8 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
diff --git a/core/java/android/util/DebugUtils.java b/core/java/android/util/DebugUtils.java
index bc5edf8..6d5e830 100644
--- a/core/java/android/util/DebugUtils.java
+++ b/core/java/android/util/DebugUtils.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import java.io.PrintWriter;
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 451a669..9f6065e 100755
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.SystemProperties;
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
index 65d825a..c9dc05b 100644
--- a/core/java/android/util/EventLog.java
+++ b/core/java/android/util/EventLog.java
@@ -17,7 +17,7 @@
package android.util;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.io.BufferedReader;
import java.io.FileReader;
diff --git a/core/java/android/util/IconDrawableFactory.java b/core/java/android/util/IconDrawableFactory.java
index d86ebf3..721e6b3 100644
--- a/core/java/android/util/IconDrawableFactory.java
+++ b/core/java/android/util/IconDrawableFactory.java
@@ -15,8 +15,8 @@
*/
package android.util;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index 6a6bccf..fda5e0d 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.SystemClock;
import java.io.FileDescriptor;
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 50779031..3f679bba 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.DeadSystemException;
import com.android.internal.os.RuntimeInit;
diff --git a/core/java/android/util/LogWriter.java b/core/java/android/util/LogWriter.java
index b062ace..a674ae1 100644
--- a/core/java/android/util/LogWriter.java
+++ b/core/java/android/util/LogWriter.java
@@ -16,7 +16,8 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.Writer;
/** @hide */
diff --git a/core/java/android/util/LongArray.java b/core/java/android/util/LongArray.java
index 6f4aa52..93bcd6b 100644
--- a/core/java/android/util/LongArray.java
+++ b/core/java/android/util/LongArray.java
@@ -17,7 +17,7 @@
package android.util;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index a0edd04..c05dd9d 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import com.android.internal.util.ArrayUtils;
diff --git a/core/java/android/util/LruCache.java b/core/java/android/util/LruCache.java
index 3cbf727d..3f7fdd8 100644
--- a/core/java/android/util/LruCache.java
+++ b/core/java/android/util/LruCache.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.util.LinkedHashMap;
import java.util.Map;
diff --git a/core/java/android/util/MathUtils.java b/core/java/android/util/MathUtils.java
index 0eeef70..971e161 100644
--- a/core/java/android/util/MathUtils.java
+++ b/core/java/android/util/MathUtils.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
/**
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index 5240786..2223d14 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
@@ -183,12 +183,11 @@
*
* @throws IllegalStateException if there is no cached value
*/
- @UnsupportedAppUsage
public TimestampedValue<Long> getCachedNtpTimeSignal() {
if (!mHasCache) {
throw new IllegalStateException("Missing authoritative time source");
}
- if (LOGD) Log.d(TAG, "currentTimeMillis() cache hit");
+ if (LOGD) Log.d(TAG, "getCachedNtpTimeSignal() cache hit");
return new TimestampedValue<>(mCachedNtpElapsedRealtime, mCachedNtpTime);
}
diff --git a/core/java/android/util/PathParser.java b/core/java/android/util/PathParser.java
index 5342d5d..1e5ec0b 100644
--- a/core/java/android/util/PathParser.java
+++ b/core/java/android/util/PathParser.java
@@ -14,7 +14,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Path;
import dalvik.annotation.optimization.FastNative;
diff --git a/core/java/android/util/Pools.java b/core/java/android/util/Pools.java
index e242fe5..7ae32441 100644
--- a/core/java/android/util/Pools.java
+++ b/core/java/android/util/Pools.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Helper class for crating pools of objects. An example use looks like this:
diff --git a/core/java/android/util/Rational.java b/core/java/android/util/Rational.java
index 39e8b14..5930000 100644
--- a/core/java/android/util/Rational.java
+++ b/core/java/android/util/Rational.java
@@ -15,9 +15,10 @@
*/
package android.util;
-import static com.android.internal.util.Preconditions.*;
+import static com.android.internal.util.Preconditions.checkNotNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
+
import java.io.IOException;
import java.io.InvalidObjectException;
diff --git a/core/java/android/util/RecurrenceRule.java b/core/java/android/util/RecurrenceRule.java
index 9c60228..a570e5e 100644
--- a/core/java/android/util/RecurrenceRule.java
+++ b/core/java/android/util/RecurrenceRule.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/util/Singleton.java b/core/java/android/util/Singleton.java
index 15c6b5b..92646b4 100644
--- a/core/java/android/util/Singleton.java
+++ b/core/java/android/util/Singleton.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Singleton helper class for lazily initialization.
diff --git a/core/java/android/util/Slog.java b/core/java/android/util/Slog.java
index a85120f..2c8bbbf 100644
--- a/core/java/android/util/Slog.java
+++ b/core/java/android/util/Slog.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
/**
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index d3367c10..dae760f 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index d6e0e53..846df39 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index 1ca1717..d4f6685 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 74cff20..8439f5a 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.SystemClock;
diff --git a/core/java/android/util/TrustedTime.java b/core/java/android/util/TrustedTime.java
index c78665d..1360f87 100644
--- a/core/java/android/util/TrustedTime.java
+++ b/core/java/android/util/TrustedTime.java
@@ -16,7 +16,7 @@
package android.util;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Interface that provides trusted time information, possibly coming from an NTP
diff --git a/core/java/android/util/XmlPullAttributes.java b/core/java/android/util/XmlPullAttributes.java
index 32fe16f..d83b355 100644
--- a/core/java/android/util/XmlPullAttributes.java
+++ b/core/java/android/util/XmlPullAttributes.java
@@ -16,13 +16,12 @@
package android.util;
-import org.xmlpull.v1.XmlPullParser;
-
-import android.annotation.UnsupportedAppUsage;
-import android.util.AttributeSet;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.XmlUtils;
+import org.xmlpull.v1.XmlPullParser;
+
/**
* Provides an implementation of AttributeSet on top of an XmlPullParser.
*/
diff --git a/core/java/android/view/AccessibilityIterators.java b/core/java/android/view/AccessibilityIterators.java
index 5f9bf39..bee04f4 100644
--- a/core/java/android/view/AccessibilityIterators.java
+++ b/core/java/android/view/AccessibilityIterators.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Configuration;
import java.text.BreakIterator;
diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java
index 6b200e1..d9f9d03 100644
--- a/core/java/android/view/ActionMode.java
+++ b/core/java/android/view/ActionMode.java
@@ -19,10 +19,9 @@
import android.annotation.StringRes;
import android.annotation.TestApi;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
/**
* Represents a contextual mode of the user interface. Action modes can be used to provide
* alternative interaction modes and replace parts of the normal UI until finished.
diff --git a/core/java/android/view/ActionProvider.java b/core/java/android/view/ActionProvider.java
index cd7e67e..e1be0fe 100644
--- a/core/java/android/view/ActionProvider.java
+++ b/core/java/android/view/ActionProvider.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.util.Log;
diff --git a/core/java/android/view/AppTransitionAnimationSpec.java b/core/java/android/view/AppTransitionAnimationSpec.java
index 4c0ed52..330061f 100644
--- a/core/java/android/view/AppTransitionAnimationSpec.java
+++ b/core/java/android/view/AppTransitionAnimationSpec.java
@@ -1,6 +1,6 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.os.Parcel;
diff --git a/core/java/android/view/BatchedInputEventReceiver.java b/core/java/android/view/BatchedInputEventReceiver.java
index 61ccac9..95b2c70 100644
--- a/core/java/android/view/BatchedInputEventReceiver.java
+++ b/core/java/android/view/BatchedInputEventReceiver.java
@@ -16,7 +16,7 @@
package android.view;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Looper;
/**
diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java
index f8bcb00..a22f5a5 100644
--- a/core/java/android/view/WindowManagerPolicyConstants.java
+++ b/core/java/android/view/WindowManagerPolicyConstants.java
@@ -72,12 +72,6 @@
"android.intent.action.USER_ACTIVITY_NOTIFICATION";
/**
- * Broadcast sent when a (custom) bugreport is requested.
- */
- String ACTION_CUSTOM_BUGREPORT_REQUESTED =
- "android.intent.action.CUSTOM_BUGREPORT_REQUESTED";
-
- /**
* Sticky broadcast of the current HDMI plugged state.
*/
String ACTION_HDMI_PLUGGED = "android.intent.action.HDMI_PLUGGED";
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 0340cb3..a0cf534 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1462,7 +1462,11 @@
return false;
}
- void onTouchEvent(MotionEvent event) {
+ /**
+ * Handles touch events on an editable text view, implementing cursor movement, selection, etc.
+ */
+ @VisibleForTesting
+ public void onTouchEvent(MotionEvent event) {
final boolean filterOutEvent = shouldFilterOutTouchEvent(event);
mLastButtonState = event.getButtonState();
if (filterOutEvent) {
@@ -2424,7 +2428,9 @@
return mSelectionControllerEnabled;
}
- private InsertionPointCursorController getInsertionController() {
+ /** Returns the controller for the insertion cursor. */
+ @VisibleForTesting
+ public @Nullable InsertionPointCursorController getInsertionController() {
if (!mInsertionControllerEnabled) {
return null;
}
@@ -2439,8 +2445,9 @@
return mInsertionPointCursorController;
}
- @Nullable
- SelectionModifierCursorController getSelectionController() {
+ /** Returns the controller for selection. */
+ @VisibleForTesting
+ public @Nullable SelectionModifierCursorController getSelectionController() {
if (!mSelectionControllerEnabled) {
return null;
}
@@ -5723,11 +5730,16 @@
}
}
- class InsertionPointCursorController implements CursorController {
+ /** Controller for the insertion cursor. */
+ @VisibleForTesting
+ public class InsertionPointCursorController implements CursorController {
private InsertionHandleView mHandle;
private boolean mIsDraggingCursor;
public void onTouchEvent(MotionEvent event) {
+ if (getSelectionController().isCursorBeingModified()) {
+ return;
+ }
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mIsDraggingCursor = false;
@@ -5738,7 +5750,8 @@
} else if (FLAG_ENABLE_CURSOR_DRAG
&& mTextView.getLayout() != null
&& mTextView.isFocused()
- && mTouchState.isMovedEnoughForDrag()) {
+ && mTouchState.isMovedEnoughForDrag()
+ && !mTouchState.isDragCloseToVertical()) {
startCursorDrag(event);
}
break;
@@ -5899,7 +5912,9 @@
}
}
- class SelectionModifierCursorController implements CursorController {
+ /** Controller for selection. */
+ @VisibleForTesting
+ public class SelectionModifierCursorController implements CursorController {
// The cursor controller handles, lazily created when shown.
private SelectionHandleView mStartHandle;
private SelectionHandleView mEndHandle;
diff --git a/core/java/android/widget/EditorTouchState.java b/core/java/android/widget/EditorTouchState.java
index 3798d00..d53099d 100644
--- a/core/java/android/widget/EditorTouchState.java
+++ b/core/java/android/widget/EditorTouchState.java
@@ -56,6 +56,7 @@
private boolean mMultiTapInSameArea;
private boolean mMovedEnoughForDrag;
+ private boolean mIsDragCloseToVertical;
public float getLastDownX() {
return mLastDownX;
@@ -94,6 +95,10 @@
return mMovedEnoughForDrag;
}
+ public boolean isDragCloseToVertical() {
+ return mIsDragCloseToVertical;
+ }
+
/**
* Updates the state based on the new event.
*/
@@ -129,6 +134,7 @@
mLastDownX = event.getX();
mLastDownY = event.getY();
mMovedEnoughForDrag = false;
+ mIsDragCloseToVertical = false;
} else if (action == MotionEvent.ACTION_UP) {
if (TextView.DEBUG_CURSOR) {
logCursor("EditorTouchState", "ACTION_UP");
@@ -137,9 +143,24 @@
mLastUpY = event.getY();
mLastUpMillis = event.getEventTime();
mMovedEnoughForDrag = false;
+ mIsDragCloseToVertical = false;
} else if (action == MotionEvent.ACTION_MOVE) {
- mMovedEnoughForDrag = !isDistanceWithin(mLastDownX, mLastDownY,
- event.getX(), event.getY(), config.getScaledTouchSlop());
+ if (!mMovedEnoughForDrag) {
+ float deltaX = event.getX() - mLastDownX;
+ float deltaY = event.getY() - mLastDownY;
+ float deltaXSquared = deltaX * deltaX;
+ float distanceSquared = (deltaXSquared) + (deltaY * deltaY);
+ int touchSlop = config.getScaledTouchSlop();
+ mMovedEnoughForDrag = distanceSquared > touchSlop * touchSlop;
+ if (mMovedEnoughForDrag) {
+ // If the direction of the swipe motion is within 30 degrees of vertical, it is
+ // considered a vertical drag. We don't actually have to compute the angle to
+ // implement the check though. When the angle is exactly 30 degrees from
+ // vertical, 2*deltaX = distance. When the angle is less than 30 degrees from
+ // vertical, 2*deltaX < distance.
+ mIsDragCloseToVertical = (4 * deltaXSquared) <= distanceSquared;
+ }
+ }
}
}
diff --git a/core/java/com/android/ims/internal/uce/common/CapInfo.java b/core/java/com/android/ims/internal/uce/common/CapInfo.java
index a9847ba..c45a3a4 100644
--- a/core/java/com/android/ims/internal/uce/common/CapInfo.java
+++ b/core/java/com/android/ims/internal/uce/common/CapInfo.java
@@ -16,10 +16,9 @@
package com.android.ims.internal.uce.common;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
/** Class for capability discovery information.
* @hide */
diff --git a/core/java/com/android/ims/internal/uce/common/StatusCode.java b/core/java/com/android/ims/internal/uce/common/StatusCode.java
index 7250eee..7f69493 100644
--- a/core/java/com/android/ims/internal/uce/common/StatusCode.java
+++ b/core/java/com/android/ims/internal/uce/common/StatusCode.java
@@ -16,10 +16,9 @@
package com.android.ims.internal.uce.common;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
/** Class for UCE status codes.
diff --git a/core/java/com/android/ims/internal/uce/common/UceLong.java b/core/java/com/android/ims/internal/uce/common/UceLong.java
index 7207899..bf51447 100644
--- a/core/java/com/android/ims/internal/uce/common/UceLong.java
+++ b/core/java/com/android/ims/internal/uce/common/UceLong.java
@@ -16,10 +16,9 @@
package com.android.ims.internal.uce.common;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
/** Simple object wrapper for a long type.
diff --git a/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java b/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
index bcb9f2d..1da5a24 100644
--- a/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
+++ b/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
@@ -15,11 +15,11 @@
*/
package com.android.ims.internal.uce.options;
-import android.annotation.UnsupportedAppUsage;
-import com.android.ims.internal.uce.common.CapInfo;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
+
+import com.android.ims.internal.uce.common.CapInfo;
/** @hide */
public class OptionsCapInfo implements Parcelable {
diff --git a/core/java/com/android/ims/internal/uce/options/OptionsCmdId.java b/core/java/com/android/ims/internal/uce/options/OptionsCmdId.java
index 14c64ac..401ca2f 100644
--- a/core/java/com/android/ims/internal/uce/options/OptionsCmdId.java
+++ b/core/java/com/android/ims/internal/uce/options/OptionsCmdId.java
@@ -17,7 +17,7 @@
package com.android.ims.internal.uce.options;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java b/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
index 4af3e6e..70a7a84 100644
--- a/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
+++ b/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
@@ -16,13 +16,13 @@
package com.android.ims.internal.uce.options;
-import com.android.ims.internal.uce.common.StatusCode;
-import com.android.ims.internal.uce.common.CapInfo;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.ims.internal.uce.common.CapInfo;
+import com.android.ims.internal.uce.common.StatusCode;
+
/** @hide */
public class OptionsCmdStatus implements Parcelable {
diff --git a/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java b/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
index c5f333d..5afddf0 100644
--- a/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
+++ b/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.options;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java b/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java
index 745df5b..1a3a028 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java
@@ -16,12 +16,12 @@
package com.android.ims.internal.uce.presence;
-import com.android.ims.internal.uce.common.CapInfo;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.ims.internal.uce.common.CapInfo;
+
/** @hide */
public class PresCapInfo implements Parcelable {
diff --git a/core/java/com/android/ims/internal/uce/presence/PresCmdId.java b/core/java/com/android/ims/internal/uce/presence/PresCmdId.java
index 41020ec..fba0c77 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresCmdId.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresCmdId.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java b/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
index ff8069c..fbc64b8 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
@@ -16,12 +16,12 @@
package com.android.ims.internal.uce.presence;
-import com.android.ims.internal.uce.common.StatusCode;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.ims.internal.uce.common.StatusCode;
+
/** @hide */
public class PresCmdStatus implements Parcelable{
diff --git a/core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java b/core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
index 87193e3..a50a22f 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresPublishTriggerType.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresResInfo.java b/core/java/com/android/ims/internal/uce/presence/PresResInfo.java
index 237c999..af9b056 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresResInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresResInfo.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java b/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
index 29699ea..9f37251 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
@@ -16,9 +16,10 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+
import java.util.Arrays;
/** @hide */
diff --git a/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java b/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
index ab46e4b..65b9fdb 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresServiceInfo.java b/core/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
index 83ba722..5eafa0f 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresServiceInfo.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java b/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java
index 5e42592..45b02f3 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java b/core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
index bee928c..ab1e17c 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresSubscriptionState.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/ims/internal/uce/presence/PresTupleInfo.java b/core/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
index 7a47786..3608eb6a 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresTupleInfo.java
@@ -16,7 +16,7 @@
package com.android.ims.internal.uce.presence;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 1cc6d78..b6b548c 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -2434,11 +2434,6 @@
FooterViewHolder(View itemView) {
super(itemView);
}
-
- public void setHeight(int height) {
- itemView.setLayoutParams(
- new RecyclerView.LayoutParams(LayoutParams.MATCH_PARENT, height));
- }
}
/**
@@ -2471,7 +2466,7 @@
private boolean mLayoutRequested = false;
- private FooterViewHolder mFooterViewHolder;
+ private int mFooterHeight = 0;
private static final int VIEW_TYPE_DIRECT_SHARE = 0;
private static final int VIEW_TYPE_NORMAL = 1;
@@ -2490,9 +2485,6 @@
mChooserListAdapter = wrappedAdapter;
mLayoutInflater = LayoutInflater.from(ChooserActivity.this);
- mFooterViewHolder = new FooterViewHolder(
- new Space(ChooserActivity.this.getApplicationContext()));
-
mShowAzLabelIfPoss = getNumSheetExpansions() < NUM_EXPANSIONS_TO_HIDE_AZ_LABEL;
wrappedAdapter.registerDataSetObserver(new DataSetObserver() {
@@ -2511,7 +2503,7 @@
}
public void setFooterHeight(int height) {
- mFooterViewHolder.setHeight(height);
+ mFooterHeight = height;
}
/**
@@ -2614,7 +2606,10 @@
case VIEW_TYPE_CALLER_AND_RANK:
return createItemGroupViewHolder(viewType, parent);
case VIEW_TYPE_FOOTER:
- return mFooterViewHolder;
+ Space sp = new Space(parent.getContext());
+ sp.setLayoutParams(new RecyclerView.LayoutParams(
+ LayoutParams.MATCH_PARENT, mFooterHeight));
+ return new FooterViewHolder(sp);
default:
// Since we catch all possible viewTypes above, no chance this is being called.
return null;
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 4e764fc..dabaf5a 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -58,10 +58,12 @@
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, in List<String> ops, long beginTimeMillis,
- long endTimeMillis, int flags, in RemoteCallback callback);
- void getHistoricalOpsFromDiskRaw(int uid, String packageName, in List<String> ops,
- long beginTimeMillis, long endTimeMillis, int flags, in RemoteCallback callback);
+ void getHistoricalOps(int uid, String packageName, String featureId, in List<String> ops,
+ int filter, long beginTimeMillis, long endTimeMillis, int flags,
+ in RemoteCallback callback);
+ void getHistoricalOpsFromDiskRaw(int uid, String packageName, String featureId,
+ in List<String> ops, int filter, long beginTimeMillis, long endTimeMillis, int flags,
+ in RemoteCallback callback);
void offsetHistory(long duration);
void setHistoryParameters(int mode, long baseSnapshotInterval, int compressionStep);
void addHistoricalOps(in AppOpsManager.HistoricalOps ops);
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 6c7e3dc..6fd271c 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -62,4 +62,6 @@
void onOutgoingEmergencySms(in EmergencyNumber sentEmergencyNumber);
void onCallDisconnectCauseChanged(in int disconnectCause, in int preciseDisconnectCause);
void onImsCallDisconnectCauseChanged(in ImsReasonInfo imsReasonInfo);
+ void onRegistrationFailed(in CellIdentity cellIdentity,
+ String chosenPlmn, int domain, int causeCode, int additionalCauseCode);
}
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 4e40503..6933f16 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -97,4 +97,6 @@
void notifyCallQualityChanged(in CallQuality callQuality, int phoneId, int subId,
int callNetworkType);
void notifyImsDisconnectCause(int subId, in ImsReasonInfo imsReasonInfo);
+ void notifyRegistrationFailed(int slotIndex, int subId, in CellIdentity cellIdentity,
+ String chosenPlmn, int domain, int causeCode, int additionalCauseCode);
}
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 1bb2ba2..e0c3823 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -187,7 +187,7 @@
public void setCollapsed(boolean collapsed) {
if (!isLaidOut()) {
- mOpenOnLayout = collapsed;
+ mOpenOnLayout = !collapsed;
} else {
smoothScrollTo(collapsed ? mCollapsibleHeight : 0, 0);
}
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index a98d7db..d5384a1 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -115,7 +115,7 @@
option (android.msg_privacy).dest = DEST_EXPLICIT;
optional SettingProto backup_agent_timeout_parameters = 1;
- optional SettingProto backup_multi_user_enabled = 2;
+ reserved 2; // Used to be backup_multi_user_enabled which was never used
}
optional Backup backup = 146;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e0603c1..31faff6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -96,7 +96,6 @@
<protected-broadcast android:name="android.intent.action.USER_ACTIVITY_NOTIFICATION" />
<protected-broadcast android:name="android.intent.action.MY_PACKAGE_SUSPENDED" />
<protected-broadcast android:name="android.intent.action.MY_PACKAGE_UNSUSPENDED" />
- <protected-broadcast android:name="android.intent.action.CUSTOM_BUGREPORT_REQUESTED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index bbc09a3..e839709 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4284,9 +4284,4 @@
<!-- Whether or not to use assistant stream volume separately from music volume -->
<bool name="config_useAssistantVolume">false</bool>
-
- <!-- Whether to use a custom Bugreport handling. When true, ACTION_CUSTOM_BUGREPORT_REQUESTED
- intent is broadcasted on bugreporting chord (instead of the default full bugreport
- generation). -->
- <bool name="config_customBugreport">false</bool>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d12d069..817ccde 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3007,6 +3007,7 @@
<public name="preferMinimalPostProcessing"/>
<public name="featureId" />
<public name="supportsInlineSuggestions" />
+ <public name="crossProfile" />
</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 ccc0ad8..129c862 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3800,5 +3800,5 @@
<!-- Assistant handles -->
<java-symbol type="dimen" name="assist_handle_shadow_radius" />
- <java-symbol type="bool" name="config_customBugreport" />
+
</resources>
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index ae835e4..84c42db 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -20,6 +20,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.testng.Assert.assertThrows;
+
import android.content.ContentResolver;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
@@ -44,9 +46,11 @@
private static final String KEY = "key1";
private static final String KEY2 = "key2";
private static final String KEY3 = "key3";
+ private static final String KEY4 = "key4";
private static final String VALUE = "value1";
private static final String VALUE2 = "value2";
private static final String VALUE3 = "value3";
+ private static final String NULL_VALUE = "null";
@After
public void cleanUp() {
@@ -561,6 +565,78 @@
assertThat(properties.getFloat("key5", 0f)).isEqualTo(floatValue);
}
+ @Test
+ public void banNamespaceProperties() throws DeviceConfig.BadConfigException {
+ // Given namespace will be permanently banned, thus it needs to be different every time
+ final String namespaceToBan = NAMESPACE + System.currentTimeMillis();
+ Properties properties = new Properties.Builder(namespaceToBan).setString(KEY, VALUE)
+ .setString(KEY4, NULL_VALUE).build();
+ // Set namespace properties
+ DeviceConfig.setProperties(properties);
+ // Ban namespace with related properties
+ DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, namespaceToBan);
+ // Verify given namespace properties are banned
+ assertThrows(DeviceConfig.BadConfigException.class,
+ () -> DeviceConfig.setProperties(properties));
+ // Modify properties and verify we can set them
+ Properties modifiedProperties = new Properties.Builder(namespaceToBan).setString(KEY, VALUE)
+ .setString(KEY4, NULL_VALUE).setString(KEY2, VALUE2).build();
+ DeviceConfig.setProperties(modifiedProperties);
+ modifiedProperties = DeviceConfig.getProperties(namespaceToBan);
+ assertThat(modifiedProperties.getKeyset()).containsExactly(KEY, KEY2, KEY4);
+ assertThat(modifiedProperties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
+ assertThat(modifiedProperties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+ // Since value is null DEFAULT_VALUE should be returned
+ assertThat(modifiedProperties.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+ }
+
+ @Test
+ public void banEntireDeviceConfig() throws DeviceConfig.BadConfigException {
+ // Given namespaces will be permanently banned, thus they need to be different every time
+ final String namespaceToBan1 = NAMESPACE + System.currentTimeMillis();
+ final String namespaceToBan2 = NAMESPACE + System.currentTimeMillis() + 1;
+
+ // Set namespaces properties
+ Properties properties1 = new Properties.Builder(namespaceToBan1).setString(KEY, VALUE)
+ .setString(KEY4, NULL_VALUE).build();
+ DeviceConfig.setProperties(properties1);
+ Properties properties2 = new Properties.Builder(namespaceToBan2).setString(KEY2, VALUE2)
+ .setString(KEY4, NULL_VALUE).build();
+ DeviceConfig.setProperties(properties2);
+
+ // Ban entire DeviceConfig
+ DeviceConfig.resetToDefaults(Settings.RESET_MODE_PACKAGE_DEFAULTS, null);
+
+ // Verify given namespace properties are banned
+ assertThrows(DeviceConfig.BadConfigException.class,
+ () -> DeviceConfig.setProperties(properties1));
+ assertThrows(DeviceConfig.BadConfigException.class,
+ () -> DeviceConfig.setProperties(properties2));
+
+ // Modify properties and verify we can set them
+ Properties modifiedProperties1 = new Properties.Builder(namespaceToBan1).setString(KEY,
+ VALUE)
+ .setString(KEY4, NULL_VALUE).setString(KEY2, VALUE2).build();
+ DeviceConfig.setProperties(modifiedProperties1);
+ modifiedProperties1 = DeviceConfig.getProperties(namespaceToBan1);
+ assertThat(modifiedProperties1.getKeyset()).containsExactly(KEY, KEY2, KEY4);
+ assertThat(modifiedProperties1.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
+ assertThat(modifiedProperties1.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+ // Since value is null DEFAULT_VALUE should be returned
+ assertThat(modifiedProperties1.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+
+ Properties modifiedProperties2 = new Properties.Builder(namespaceToBan2).setString(KEY,
+ VALUE)
+ .setString(KEY4, NULL_VALUE).setString(KEY2, VALUE2).build();
+ DeviceConfig.setProperties(modifiedProperties1);
+ modifiedProperties2 = DeviceConfig.getProperties(namespaceToBan1);
+ assertThat(modifiedProperties2.getKeyset()).containsExactly(KEY, KEY2, KEY4);
+ assertThat(modifiedProperties2.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE);
+ assertThat(modifiedProperties2.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+ // Since value is null DEFAULT_VALUE should be returned
+ assertThat(modifiedProperties2.getString(KEY4, DEFAULT_VALUE)).isEqualTo(DEFAULT_VALUE);
+ }
+
// TODO(mpape): resolve b/142727848 and re-enable listener tests
// @Test
// public void onPropertiesChangedListener_setPropertyCallback() throws InterruptedException {
diff --git a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
index b4f2c91..f497db2 100644
--- a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
+++ b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
@@ -16,15 +16,23 @@
package android.widget;
+import static android.widget.espresso.TextViewActions.clickOnTextAtIndex;
import static android.widget.espresso.TextViewActions.dragOnText;
import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex;
+import static android.widget.espresso.TextViewAssertions.hasSelection;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.replaceText;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static org.hamcrest.Matchers.emptyString;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
import android.app.Activity;
import android.app.Instrumentation;
+import android.view.MotionEvent;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -70,107 +78,247 @@
onView(withId(R.id.textview)).perform(replaceText(text));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
- // Drag left to right. The cursor should end up at the position where the finger is lifted.
+ // Swipe left to right to drag the cursor. The cursor should end up at the position where
+ // the finger is lifted.
onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("llo"), text.indexOf("!")));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(11));
- // Drag right to left. The cursor should end up at the position where the finger is lifted.
+ // Swipe right to left to drag the cursor. The cursor should end up at the position where
+ // the finger is lifted.
onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("!"), text.indexOf("llo")));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(2));
}
@Test
public void testCursorDrag_horizontal_whenTextViewContentsLargerThanScreen() throws Throwable {
- String text = "Hello world!"
- + Strings.repeat("\n", 500) + "012345middle"
- + Strings.repeat("\n", 10) + "012345last";
+ String text = "Hello world!\n\n"
+ + Strings.repeat("Bla\n\n", 200) + "Bye";
onView(withId(R.id.textview)).perform(replaceText(text));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
- // Drag left to right. The cursor should end up at the position where the finger is lifted.
+ // Swipe left to right to drag the cursor. The cursor should end up at the position where
+ // the finger is lifted.
onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("llo"), text.indexOf("!")));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(11));
- // Drag right to left. The cursor should end up at the position where the finger is lifted.
+ // Swipe right to left to drag the cursor. The cursor should end up at the position where
+ // the finger is lifted.
onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("!"), text.indexOf("llo")));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(2));
}
@Test
+ public void testCursorDrag_diagonal_whenTextViewContentsFitOnScreen() throws Throwable {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 1; i <= 9; i++) {
+ sb.append("line").append(i).append("\n");
+ }
+ String text = sb.toString();
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+
+ // Swipe along a diagonal path. This should drag the cursor.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("2")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("2")));
+
+ // Swipe along a steeper diagonal path. This should still drag the cursor.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("3")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("3")));
+
+ // Swipe right-down along a very steep diagonal path. This should not drag the cursor.
+ // Normally this would trigger a scroll, but since the full view fits on the screen there
+ // is nothing to scroll and the gesture will trigger a selection drag.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("7")));
+ onView(withId(R.id.textview)).check(hasSelection(not(emptyString())));
+
+ // Swipe right-up along a very steep diagonal path. This should not drag the cursor.
+ // Normally this would trigger a scroll, but since the full view fits on the screen there
+ // is nothing to scroll and the gesture will trigger a selection drag.
+ int index = text.indexOf("line9");
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(index));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(index));
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line7"), text.indexOf("1")));
+ onView(withId(R.id.textview)).check(hasSelection(not(emptyString())));
+ }
+
+ @Test
public void testCursorDrag_diagonal_whenTextViewContentsLargerThanScreen() throws Throwable {
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 9; i++) {
sb.append("line").append(i).append("\n");
}
- sb.append(Strings.repeat("0123456789\n\n", 500)).append("Last line");
+ sb.append(Strings.repeat("0123456789\n", 400)).append("Last");
String text = sb.toString();
onView(withId(R.id.textview)).perform(replaceText(text));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
- // Drag along a diagonal path.
+ // Swipe along a diagonal path. This should drag the cursor.
onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("2")));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("2")));
- // Drag along a steeper diagonal path.
- onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("9")));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("9")));
+ // Swipe along a steeper diagonal path. This should still drag the cursor.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("3")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("3")));
- // Drag along an almost vertical path.
- // TODO(b/145833335): Consider whether this should scroll instead of dragging the cursor.
- onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("ne1"), text.indexOf("9")));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("9")));
+ // Swipe right-down along a very steep diagonal path. This should not drag the cursor.
+ // Normally this would trigger a scroll up, but since the view is already at the top there
+ // is nothing to scroll and the gesture will trigger a selection drag.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("7")));
+ onView(withId(R.id.textview)).check(hasSelection(not(emptyString())));
- // Drag along a vertical path from line 1 to line 9.
- // TODO(b/145833335): Consider whether this should scroll instead of dragging the cursor.
- onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("e1"), text.indexOf("e9")));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("e9")));
-
- // Drag along a vertical path from line 9 to line 1.
- // TODO(b/145833335): Consider whether this should scroll instead of dragging the cursor.
- onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("e9"), text.indexOf("e1")));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("e1")));
+ // Swipe right-up along a very steep diagonal path. This should not drag the cursor. This
+ // will trigger a downward scroll and the cursor position will not change.
+ int index = text.indexOf("line9");
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(index));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(index));
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line7"), text.indexOf("1")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(index));
}
@Test
public void testCursorDrag_vertical_whenTextViewContentsFitOnScreen() throws Throwable {
- String text = "012first\n\n" + Strings.repeat("012345\n\n", 10) + "012last";
+ String text = "012345_aaa\n"
+ + "0123456789\n"
+ + "012345_bbb\n"
+ + "0123456789\n"
+ + "012345_ccc\n"
+ + "0123456789\n"
+ + "012345_ddd";
onView(withId(R.id.textview)).perform(replaceText(text));
+
+ // Swipe up vertically. This should not drag the cursor. Since there's also nothing to
+ // scroll, the gesture will trigger a selection drag.
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(0));
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("bbb"), text.indexOf("aaa")));
+ onView(withId(R.id.textview)).check(hasSelection(not(emptyString())));
- // Drag down. Since neither the TextView nor its container require scrolling, the cursor
- // drag should execute and the cursor should end up at the position where the finger is
- // lifted.
- onView(withId(R.id.textview)).perform(
- dragOnText(text.indexOf("first"), text.indexOf("last")));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.length() - 4));
-
- // Drag up. Since neither the TextView nor its container require scrolling, the cursor
- // drag should execute and the cursor should end up at the position where the finger is
- // lifted.
- onView(withId(R.id.textview)).perform(
- dragOnText(text.indexOf("last"), text.indexOf("first")));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(3));
+ // Swipe down vertically. This should not drag the cursor. Since there's also nothing to
+ // scroll, the gesture will trigger a selection drag.
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(0));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("ccc"), text.indexOf("ddd")));
+ onView(withId(R.id.textview)).check(hasSelection(not(emptyString())));
}
@Test
public void testCursorDrag_vertical_whenTextViewContentsLargerThanScreen() throws Throwable {
- String text = "012345first\n\n"
- + Strings.repeat("0123456789\n\n", 10) + "012345middle"
- + Strings.repeat("0123456789\n\n", 500) + "012345last";
+ String text = "012345_aaa\n"
+ + "0123456789\n"
+ + "012345_bbb\n"
+ + "0123456789\n"
+ + "012345_ccc\n"
+ + "0123456789\n"
+ + "012345_ddd\n"
+ + Strings.repeat("0123456789\n", 400) + "012345_zzz";
onView(withId(R.id.textview)).perform(replaceText(text));
- int initialCursorPosition = 0;
+ onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf("ddd")));
+ int initialCursorPosition = text.indexOf("ddd");
onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(initialCursorPosition));
- // Drag up.
- // TODO(b/145833335): Consider whether this should scroll instead of dragging the cursor.
- onView(withId(R.id.textview)).perform(
- dragOnText(text.indexOf("middle"), text.indexOf("first")));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("first")));
+ // Swipe up vertically. This should trigger a downward scroll.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("bbb"), text.indexOf("aaa")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(initialCursorPosition));
- // Drag down.
- // TODO(b/145833335): Consider whether this should scroll instead of dragging the cursor.
- onView(withId(R.id.textview)).perform(
- dragOnText(text.indexOf("first"), text.indexOf("middle")));
- onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("middle")));
+ // Swipe down vertically. This should trigger an upward scroll.
+ onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("ccc"), text.indexOf("ddd")));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(initialCursorPosition));
+ }
+
+ @Test
+ public void testEditor_onTouchEvent_cursorDrag() throws Throwable {
+ String text = "testEditor_onTouchEvent_cursorDrag";
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+
+ TextView tv = mActivity.findViewById(R.id.textview);
+ Editor editor = tv.getEditorForTesting();
+
+ // Simulate a tap-and-drag gesture. This should trigger a cursor drag.
+ long event1Time = 1001;
+ MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f);
+ mActivity.runOnUiThread(() -> editor.onTouchEvent(event1));
+ mInstrumentation.waitForIdleSync();
+ assertFalse(editor.getInsertionController().isCursorBeingModified());
+ assertFalse(editor.getSelectionController().isCursorBeingModified());
+
+ long event2Time = 1002;
+ MotionEvent event2 = moveEvent(event1Time, event2Time, 21f, 30f);
+ mActivity.runOnUiThread(() -> editor.onTouchEvent(event2));
+ mInstrumentation.waitForIdleSync();
+ assertFalse(editor.getInsertionController().isCursorBeingModified());
+ assertFalse(editor.getSelectionController().isCursorBeingModified());
+
+ long event3Time = 1003;
+ MotionEvent event3 = moveEvent(event3Time, event3Time, 120f, 30f);
+ mActivity.runOnUiThread(() -> editor.onTouchEvent(event3));
+ mInstrumentation.waitForIdleSync();
+ assertTrue(editor.getInsertionController().isCursorBeingModified());
+ assertFalse(editor.getSelectionController().isCursorBeingModified());
+
+ long event4Time = 1004;
+ MotionEvent event4 = upEvent(event3Time, event4Time, 120f, 30f);
+ mActivity.runOnUiThread(() -> editor.onTouchEvent(event4));
+ mInstrumentation.waitForIdleSync();
+ assertFalse(editor.getInsertionController().isCursorBeingModified());
+ assertFalse(editor.getSelectionController().isCursorBeingModified());
+ }
+
+ @Test
+ public void testEditor_onTouchEvent_selectionDrag() throws Throwable {
+ String text = "testEditor_onTouchEvent_selectionDrag";
+ onView(withId(R.id.textview)).perform(replaceText(text));
+ onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+
+ TextView tv = mActivity.findViewById(R.id.textview);
+ Editor editor = tv.getEditorForTesting();
+
+ // Simulate a double-tap followed by a drag. This should trigger a selection drag.
+ long event1Time = 1001;
+ MotionEvent event1 = downEvent(event1Time, event1Time, 20f, 30f);
+ mActivity.runOnUiThread(() -> editor.onTouchEvent(event1));
+ mInstrumentation.waitForIdleSync();
+ assertFalse(editor.getInsertionController().isCursorBeingModified());
+ assertFalse(editor.getSelectionController().isCursorBeingModified());
+
+ long event2Time = 1002;
+ MotionEvent event2 = upEvent(event1Time, event2Time, 20f, 30f);
+ mActivity.runOnUiThread(() -> editor.onTouchEvent(event2));
+ mInstrumentation.waitForIdleSync();
+ assertFalse(editor.getInsertionController().isCursorBeingModified());
+ assertFalse(editor.getSelectionController().isCursorBeingModified());
+
+ long event3Time = 1003;
+ MotionEvent event3 = downEvent(event3Time, event3Time, 20f, 30f);
+ mActivity.runOnUiThread(() -> editor.onTouchEvent(event3));
+ mInstrumentation.waitForIdleSync();
+ assertFalse(editor.getInsertionController().isCursorBeingModified());
+ assertTrue(editor.getSelectionController().isCursorBeingModified());
+
+ long event4Time = 1004;
+ MotionEvent event4 = moveEvent(event3Time, event4Time, 120f, 30f);
+ mActivity.runOnUiThread(() -> editor.onTouchEvent(event4));
+ mInstrumentation.waitForIdleSync();
+ assertFalse(editor.getInsertionController().isCursorBeingModified());
+ assertTrue(editor.getSelectionController().isCursorBeingModified());
+
+ long event5Time = 1005;
+ MotionEvent event5 = upEvent(event3Time, event5Time, 120f, 30f);
+ mActivity.runOnUiThread(() -> editor.onTouchEvent(event5));
+ mInstrumentation.waitForIdleSync();
+ assertFalse(editor.getInsertionController().isCursorBeingModified());
+ assertFalse(editor.getSelectionController().isCursorBeingModified());
+ }
+
+ private static MotionEvent downEvent(long downTime, long eventTime, float x, float y) {
+ return MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);
+ }
+
+ private static MotionEvent upEvent(long downTime, long eventTime, float x, float y) {
+ return MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
+ }
+
+ private static MotionEvent moveEvent(long downTime, long eventTime, float x, float y) {
+ return MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0);
}
}
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index aecef8e..bcb313e 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -277,6 +277,10 @@
assetFd = mResolver.openAssetFileDescriptor(mUri, "r");
}
} catch (FileNotFoundException e) {
+ // Handled below, along with the case where assetFd was set to null.
+ }
+
+ if (assetFd == null) {
// Some images cannot be opened as AssetFileDescriptors (e.g.
// bmp, ico). Open them as InputStreams.
InputStream is = mResolver.openInputStream(mUri);
@@ -286,9 +290,7 @@
return createFromStream(is, true, preferAnimation, this);
}
- if (assetFd == null) {
- throw new FileNotFoundException(mUri.toString());
- }
+
return createFromAssetFileDescriptor(assetFd, preferAnimation, this);
}
}
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 4a40c62..cad5aa6 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -16,11 +16,18 @@
package android.media.audiofx;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
+import android.media.AudioDeviceAddress;
+import android.media.AudioDeviceInfo;
+import android.media.AudioSystem;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
@@ -448,12 +455,46 @@
public AudioEffect(UUID type, UUID uuid, int priority, int audioSession)
throws IllegalArgumentException, UnsupportedOperationException,
RuntimeException {
+ this(type, uuid, priority, audioSession, null);
+ }
+
+ /**
+ * Constructs an AudioEffect attached to a particular audio device.
+ * The device does not have to be attached when the effect is created. The effect will only
+ * be applied when the device is actually selected for playback or capture.
+ * @param uuid unique identifier of a particular effect implementation.
+ * @param device the device the effect must be attached to.
+ *
+ * @throws java.lang.IllegalArgumentException
+ * @throws java.lang.UnsupportedOperationException
+ * @throws java.lang.RuntimeException
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS)
+ public AudioEffect(@NonNull UUID uuid, @NonNull AudioDeviceAddress device) {
+ this(EFFECT_TYPE_NULL, Objects.requireNonNull(uuid), 0, -2, Objects.requireNonNull(device));
+ }
+
+ private AudioEffect(UUID type, UUID uuid, int priority,
+ int audioSession, @Nullable AudioDeviceAddress device)
+ throws IllegalArgumentException, UnsupportedOperationException,
+ RuntimeException {
int[] id = new int[1];
Descriptor[] desc = new Descriptor[1];
+
+ int deviceType = AudioSystem.DEVICE_NONE;
+ String deviceAddress = "";
+ if (device != null) {
+ deviceType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType());
+ deviceAddress = device.getAddress();
+ }
+
// native initialization
int initResult = native_setup(new WeakReference<AudioEffect>(this),
- type.toString(), uuid.toString(), priority, audioSession, id,
- desc, ActivityThread.currentOpPackageName());
+ type.toString(), uuid.toString(), priority, audioSession,
+ deviceType, deviceAddress,
+ id, desc, ActivityThread.currentOpPackageName());
if (initResult != SUCCESS && initResult != ALREADY_EXISTS) {
Log.e(TAG, "Error code " + initResult
+ " when initializing AudioEffect.");
@@ -1293,7 +1334,8 @@
private static native final void native_init();
private native final int native_setup(Object audioeffect_this, String type,
- String uuid, int priority, int audioSession, int[] id, Object[] desc,
+ String uuid, int priority, int audioSession,
+ int deviceType, String deviceAddress, int[] id, Object[] desc,
String opPackageName);
private native final void native_finalize();
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 3562782..c88e2d2 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -100,7 +100,7 @@
/////////////// Dvr ///////////////////////
-Dvr::Dvr(sp<IDvr> sp, jweak obj) : mDvrSp(sp), mDvrObj(obj) {}
+Dvr::Dvr(sp<IDvr> sp, jweak obj) : mDvrSp(sp), mDvrObj(obj), mDvrMQEventFlag(nullptr) {}
Dvr::~Dvr() {
EventFlag::deleteEventFlag(&mDvrMQEventFlag);
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 747d4c01..007dd10 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -268,8 +268,9 @@
static jint
android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
- jstring type, jstring uuid, jint priority, jint sessionId, jintArray jId,
- jobjectArray javadesc, jstring opPackageName)
+ jstring type, jstring uuid, jint priority, jint sessionId,
+ jint deviceType, jstring deviceAddress,
+ jintArray jId, jobjectArray javadesc, jstring opPackageName)
{
ALOGV("android_media_AudioEffect_native_setup");
AudioEffectJniStorage* lpJniStorage = NULL;
@@ -280,6 +281,7 @@
const char *uuidStr = NULL;
effect_descriptor_t desc;
jobject jdesc;
+ AudioDeviceTypeAddr device;
ScopedUtfChars opPackageNameStr(env, opPackageName);
@@ -328,6 +330,12 @@
goto setup_failure;
}
+ if (deviceType != AUDIO_DEVICE_NONE) {
+ device.mType = deviceType;
+ ScopedUtfChars address(env, deviceAddress);
+ device.mAddress = address.c_str();
+ }
+
// create the native AudioEffect object
lpAudioEffect = new AudioEffect(typeStr,
String16(opPackageNameStr.c_str()),
@@ -336,7 +344,8 @@
effectCallback,
&lpJniStorage->mCallbackData,
(audio_session_t) sessionId,
- AUDIO_IO_HANDLE_NONE);
+ AUDIO_IO_HANDLE_NONE,
+ device);
if (lpAudioEffect == 0) {
ALOGE("Error creating AudioEffect");
goto setup_failure;
@@ -757,7 +766,7 @@
// Dalvik VM type signatures
static const JNINativeMethod gMethods[] = {
{"native_init", "()V", (void *)android_media_AudioEffect_native_init},
- {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;II[I[Ljava/lang/Object;Ljava/lang/String;)I",
+ {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;IIILjava/lang/String;[I[Ljava/lang/Object;Ljava/lang/String;)I",
(void *)android_media_AudioEffect_native_setup},
{"native_finalize", "()V", (void *)android_media_AudioEffect_native_finalize},
{"native_release", "()V", (void *)android_media_AudioEffect_native_release},
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/CryptoSettings.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/CryptoSettings.java
index 033f1b1..bb1336f 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/CryptoSettings.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/CryptoSettings.java
@@ -16,7 +16,6 @@
package com.android.server.backup.encryption;
-import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkState;
import android.content.Context;
@@ -29,6 +28,7 @@
import com.android.internal.annotations.VisibleForTesting;
import java.security.KeyStoreException;
+import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@@ -88,8 +88,8 @@
}
private CryptoSettings(SharedPreferences sharedPreferences, Context context) {
- mSharedPreferences = checkNotNull(sharedPreferences);
- mContext = checkNotNull(context);
+ mSharedPreferences = Objects.requireNonNull(sharedPreferences);
+ mContext = Objects.requireNonNull(context);
}
/**
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/BackupFileBuilder.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/BackupFileBuilder.java
index 3d3fb55..4010bfd 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/BackupFileBuilder.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/BackupFileBuilder.java
@@ -17,7 +17,6 @@
package com.android.server.backup.encryption.chunking;
import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkState;
import android.annotation.Nullable;
@@ -35,6 +34,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
/**
* Writes batches of {@link EncryptedChunk} to a diff script, and generates the associated {@link
@@ -174,7 +174,7 @@
* IllegalStateException}.
*/
public void finish(ChunksMetadataProto.ChunksMetadata metadata) throws IOException {
- checkNotNull(metadata, "Metadata cannot be null");
+ Objects.requireNonNull(metadata, "Metadata cannot be null");
long startOfMetadata = mBackupWriter.getBytesWritten();
mBackupWriter.writeBytes(ChunksMetadataProto.ChunksMetadata.toByteArray(metadata));
@@ -190,7 +190,7 @@
*/
private void writeChunkToFileAndListing(
ChunkHash chunkHash, Map<ChunkHash, EncryptedChunk> newChunks) throws IOException {
- checkNotNull(chunkHash, "Hash cannot be null");
+ Objects.requireNonNull(chunkHash, "Hash cannot be null");
if (mOldChunkListing.hasChunk(chunkHash)) {
ChunkListingMap.Entry oldChunk = mOldChunkListing.getChunkEntry(chunkHash);
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/ProtoStore.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/ProtoStore.java
index 3ba5f2b..b0a562c 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/ProtoStore.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/ProtoStore.java
@@ -16,8 +16,6 @@
package com.android.server.backup.encryption.chunking;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.content.Context;
import android.text.TextUtils;
import android.util.AtomicFile;
@@ -34,6 +32,7 @@
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
+import java.util.Objects;
import java.util.Optional;
/**
@@ -75,7 +74,7 @@
*/
@VisibleForTesting
ProtoStore(Class<T> clazz, File storeFolder) throws IOException {
- mClazz = checkNotNull(clazz);
+ mClazz = Objects.requireNonNull(clazz);
mStoreFolder = ensureDirectoryExistsOrThrow(storeFolder);
}
@@ -118,7 +117,7 @@
/** Saves a proto to disk, associating it with the given package. */
public void saveProto(String packageName, T proto) throws IOException {
- checkNotNull(proto);
+ Objects.requireNonNull(proto);
File file = getFileForPackage(packageName);
try (FileOutputStream os = new FileOutputStream(file)) {
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/Hkdf.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/Hkdf.java
index 6f4f549..c7af8c8 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/Hkdf.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/Hkdf.java
@@ -16,10 +16,9 @@
package com.android.server.backup.encryption.chunking.cdc;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
+import java.util.Objects;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
@@ -49,9 +48,9 @@
* @throws InvalidKeyException If the salt can not be used as a valid key.
*/
static byte[] hkdf(byte[] masterKey, byte[] salt, byte[] data) throws InvalidKeyException {
- checkNotNull(masterKey, "HKDF requires master key to be set.");
- checkNotNull(salt, "HKDF requires a salt.");
- checkNotNull(data, "No data provided to HKDF.");
+ Objects.requireNonNull(masterKey, "HKDF requires master key to be set.");
+ Objects.requireNonNull(salt, "HKDF requires a salt.");
+ Objects.requireNonNull(data, "No data provided to HKDF.");
return hkdfSha256Expand(hkdfSha256Extract(masterKey, salt), data);
}
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKey.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKey.java
index f356b4f..436c6de8 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKey.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKey.java
@@ -16,14 +16,14 @@
package com.android.server.backup.encryption.keys;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.annotation.IntDef;
import android.content.Context;
import android.security.keystore.recovery.InternalRecoveryServiceException;
import android.security.keystore.recovery.RecoveryController;
import android.util.Slog;
+import java.util.Objects;
+
import javax.crypto.SecretKey;
/**
@@ -46,8 +46,8 @@
* @param secretKey The key.
*/
public RecoverableKeyStoreSecondaryKey(String alias, SecretKey secretKey) {
- mAlias = checkNotNull(alias);
- mSecretKey = checkNotNull(secretKey);
+ mAlias = Objects.requireNonNull(alias);
+ mSecretKey = Objects.requireNonNull(secretKey);
}
/**
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/kv/KeyValueListingBuilder.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/kv/KeyValueListingBuilder.java
index b3518e1..217304c 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/kv/KeyValueListingBuilder.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/kv/KeyValueListingBuilder.java
@@ -17,7 +17,6 @@
package com.android.server.backup.encryption.kv;
import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
import com.android.server.backup.encryption.chunk.ChunkHash;
import com.android.server.backup.encryption.protos.nano.KeyValueListingProto;
@@ -26,6 +25,7 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
/**
* Builds a {@link KeyValueListingProto.KeyValueListing}, which is a nano proto and so has no
@@ -37,7 +37,7 @@
/** Adds a new pair entry to the listing. */
public KeyValueListingBuilder addPair(String key, ChunkHash hash) {
checkArgument(key.length() != 0, "Key must have non-zero length");
- checkNotNull(hash, "Hash must not be null");
+ Objects.requireNonNull(hash, "Hash must not be null");
KeyValueListingProto.KeyValueEntry entry = new KeyValueListingProto.KeyValueEntry();
entry.key = key;
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessor.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessor.java
index 0baec8b..71588f6 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessor.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedFullBackupDataProcessor.java
@@ -16,7 +16,6 @@
package com.android.server.backup.encryption.tasks;
-import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkState;
import android.annotation.Nullable;
@@ -34,6 +33,7 @@
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.security.SecureRandom;
+import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -67,12 +67,12 @@
SecureRandom secureRandom,
RecoverableKeyStoreSecondaryKey secondaryKey,
String packageName) {
- mContext = checkNotNull(context);
- mExecutorService = checkNotNull(executorService);
- mCryptoBackupServer = checkNotNull(cryptoBackupServer);
- mSecureRandom = checkNotNull(secureRandom);
- mSecondaryKey = checkNotNull(secondaryKey);
- mPackageName = checkNotNull(packageName);
+ mContext = Objects.requireNonNull(context);
+ mExecutorService = Objects.requireNonNull(executorService);
+ mCryptoBackupServer = Objects.requireNonNull(cryptoBackupServer);
+ mSecureRandom = Objects.requireNonNull(secureRandom);
+ mSecondaryKey = Objects.requireNonNull(secondaryKey);
+ mPackageName = Objects.requireNonNull(packageName);
}
@Override
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/RotateSecondaryKeyTask.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/RotateSecondaryKeyTask.java
index d58cb66..e5e2c1c 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/RotateSecondaryKeyTask.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/RotateSecondaryKeyTask.java
@@ -18,8 +18,6 @@
import static android.os.Build.VERSION_CODES.P;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
import android.content.Context;
import android.security.keystore.recovery.InternalRecoveryServiceException;
import android.security.keystore.recovery.RecoveryController;
@@ -42,6 +40,7 @@
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import javax.crypto.IllegalBlockSizeException;
@@ -77,10 +76,10 @@
CryptoSettings cryptoSettings,
RecoveryController recoveryController) {
mContext = context;
- mSecondaryKeyManager = checkNotNull(secondaryKeyManager);
- mCryptoSettings = checkNotNull(cryptoSettings);
- mBackupServer = checkNotNull(backupServer);
- mRecoveryController = checkNotNull(recoveryController);
+ mSecondaryKeyManager = Objects.requireNonNull(secondaryKeyManager);
+ mCryptoSettings = Objects.requireNonNull(cryptoSettings);
+ mBackupServer = Objects.requireNonNull(backupServer);
+ mRecoveryController = Objects.requireNonNull(recoveryController);
}
/** Runs the task. */
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/StartSecondaryKeyRotationTask.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/StartSecondaryKeyRotationTask.java
index 77cfded..81169e2 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/StartSecondaryKeyRotationTask.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/StartSecondaryKeyRotationTask.java
@@ -26,6 +26,7 @@
import com.android.server.backup.encryption.keys.RecoverableKeyStoreSecondaryKeyManager;
import java.security.UnrecoverableKeyException;
+import java.util.Objects;
import java.util.Optional;
/**
@@ -41,8 +42,8 @@
public StartSecondaryKeyRotationTask(
CryptoSettings cryptoSettings,
RecoverableKeyStoreSecondaryKeyManager secondaryKeyManager) {
- mCryptoSettings = Preconditions.checkNotNull(cryptoSettings);
- mSecondaryKeyManager = Preconditions.checkNotNull(secondaryKeyManager);
+ mCryptoSettings = Objects.requireNonNull(cryptoSettings);
+ mSecondaryKeyManager = Objects.requireNonNull(secondaryKeyManager);
}
/** Begin the key rotation */
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/testing/DiffScriptProcessor.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/testing/DiffScriptProcessor.java
index faddb6c..7e97924 100644
--- a/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/testing/DiffScriptProcessor.java
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/testing/DiffScriptProcessor.java
@@ -17,7 +17,6 @@
package com.android.server.backup.encryption.testing;
import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -29,6 +28,7 @@
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.Locale;
+import java.util.Objects;
import java.util.Optional;
import java.util.Scanner;
import java.util.regex.Pattern;
@@ -69,7 +69,7 @@
checkArgument(input.exists(), "input file did not exist.");
mInput = input;
mInputLength = input.length();
- mOutput = checkNotNull(output);
+ mOutput = Objects.requireNonNull(output);
}
public void process(InputStream diffScript) throws IOException, MalformedDiffScriptException {
diff --git a/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/shadows/DataEntity.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/shadows/DataEntity.java
index 6d3b5e9..06f4859 100644
--- a/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/shadows/DataEntity.java
+++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/shadows/DataEntity.java
@@ -16,10 +16,9 @@
package com.android.server.testing.shadows;
-import static com.google.common.base.Preconditions.checkNotNull;
-
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
+import java.util.Objects;
/**
* Represents a key value pair in {@link ShadowBackupDataInput} and {@link ShadowBackupDataOutput}.
@@ -34,7 +33,7 @@
* StandardCharsets#UTF_8}.
*/
public DataEntity(String key, String value) {
- this.mKey = checkNotNull(key);
+ this.mKey = Objects.requireNonNull(key);
this.mValue = value.getBytes(StandardCharsets.UTF_8);
mSize = this.mValue.length;
}
@@ -44,7 +43,7 @@
* pair.
*/
public DataEntity(String key) {
- this.mKey = checkNotNull(key);
+ this.mKey = Objects.requireNonNull(key);
mSize = -1;
mValue = null;
}
@@ -62,7 +61,7 @@
* @param size the length of the value in bytes
*/
public DataEntity(String key, byte[] data, int size) {
- this.mKey = checkNotNull(key);
+ this.mKey = Objects.requireNonNull(key);
this.mSize = size;
mValue = new byte[size];
for (int i = 0; i < size; i++) {
diff --git a/packages/CarSystemUI/res/layout/car_facet_button.xml b/packages/CarSystemUI/res/layout/car_facet_button.xml
deleted file mode 100644
index 8e7ebad..0000000
--- a/packages/CarSystemUI/res/layout/car_facet_button.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 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.
-*/
--->
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/car_facet_button"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="center"
- android:animateLayoutChanges="true"
- android:orientation="vertical">
-
- <com.android.keyguard.AlphaOptimizedImageButton
- android:id="@+id/car_nav_button_icon"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:animateLayoutChanges="true"
- android:background="@android:color/transparent"
- android:scaleType="fitCenter">
- </com.android.keyguard.AlphaOptimizedImageButton>
-
- <com.android.keyguard.AlphaOptimizedImageButton
- android:id="@+id/car_nav_button_more_icon"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:animateLayoutChanges="true"
- android:src="@drawable/car_ic_arrow"
- android:background="@android:color/transparent"
- android:scaleType="fitCenter">
- </com.android.keyguard.AlphaOptimizedImageButton>
-
- </LinearLayout>
-</merge>
diff --git a/packages/CarSystemUI/res/layout/car_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_navigation_bar.xml
index 6c7a04f..27ad4fc 100644
--- a/packages/CarSystemUI/res/layout/car_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_navigation_bar.xml
@@ -33,14 +33,14 @@
android:paddingEnd="20dp"
android:gravity="center">
- <com.android.systemui.navigationbar.car.CarFacetButton
+ <com.android.systemui.navigationbar.car.CarNavigationButton
android:id="@+id/home"
style="@style/NavigationBarButton"
systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
systemui:icon="@drawable/car_ic_overview"
systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
systemui:selectedIcon="@drawable/car_ic_overview_selected"
- systemui:useMoreIcon="false"
+ systemui:highlightWhenSelected="true"
/>
<Space
@@ -48,14 +48,14 @@
android:layout_height="match_parent"
android:layout_weight="1"/>
- <com.android.systemui.navigationbar.car.CarFacetButton
+ <com.android.systemui.navigationbar.car.CarNavigationButton
android:id="@+id/maps_nav"
style="@style/NavigationBarButton"
systemui:categories="android.intent.category.APP_MAPS"
systemui:icon="@drawable/car_ic_navigation"
systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MAPS;launchFlags=0x14000000;end"
systemui:selectedIcon="@drawable/car_ic_navigation_selected"
- systemui:useMoreIcon="false"
+ systemui:highlightWhenSelected="true"
/>
<Space
@@ -63,7 +63,7 @@
android:layout_height="match_parent"
android:layout_weight="1"/>
- <com.android.systemui.navigationbar.car.CarFacetButton
+ <com.android.systemui.navigationbar.car.CarNavigationButton
android:id="@+id/music_nav"
style="@style/NavigationBarButton"
systemui:categories="android.intent.category.APP_MUSIC"
@@ -71,7 +71,7 @@
systemui:intent="intent:#Intent;action=android.car.intent.action.MEDIA_TEMPLATE;launchFlags=0x10000000;end"
systemui:packages="com.android.car.media"
systemui:selectedIcon="@drawable/car_ic_music_selected"
- systemui:useMoreIcon="false"
+ systemui:highlightWhenSelected="true"
/>
<Space
@@ -79,14 +79,14 @@
android:layout_height="match_parent"
android:layout_weight="1"/>
- <com.android.systemui.navigationbar.car.CarFacetButton
+ <com.android.systemui.navigationbar.car.CarNavigationButton
android:id="@+id/phone_nav"
style="@style/NavigationBarButton"
systemui:icon="@drawable/car_ic_phone"
systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;package=com.android.car.dialer;launchFlags=0x10000000;end"
systemui:packages="com.android.car.dialer"
systemui:selectedIcon="@drawable/car_ic_phone_selected"
- systemui:useMoreIcon="false"
+ systemui:highlightWhenSelected="true"
/>
<Space
@@ -94,14 +94,14 @@
android:layout_height="match_parent"
android:layout_weight="1"/>
- <com.android.systemui.navigationbar.car.CarFacetButton
+ <com.android.systemui.navigationbar.car.CarNavigationButton
android:id="@+id/grid_nav"
style="@style/NavigationBarButton"
systemui:componentNames="com.android.car.carlauncher/.AppGridActivity"
systemui:icon="@drawable/car_ic_apps"
systemui:intent="intent:#Intent;component=com.android.car.carlauncher/.AppGridActivity;launchFlags=0x24000000;end"
systemui:selectedIcon="@drawable/car_ic_apps_selected"
- systemui:useMoreIcon="false"
+ systemui:highlightWhenSelected="true"
/>
<Space
@@ -115,7 +115,6 @@
systemui:icon="@drawable/car_ic_notification"
systemui:longIntent="intent:#Intent;component=com.android.car.bugreport/.BugReportActivity;end"
systemui:selectedIcon="@drawable/car_ic_notification_selected"
- systemui:useMoreIcon="false"
/>
<Space
@@ -127,7 +126,6 @@
android:id="@+id/assist"
style="@style/NavigationBarButton"
systemui:icon="@drawable/ic_mic_white"
- systemui:useMoreIcon="false"
/>
</LinearLayout>
diff --git a/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml b/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml
index 0f964fd..1c5d37f 100644
--- a/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml
+++ b/packages/CarSystemUI/res/layout/car_navigation_bar_unprovisioned.xml
@@ -31,7 +31,7 @@
android:paddingStart="@*android:dimen/car_padding_5"
android:paddingEnd="@*android:dimen/car_padding_5">
- <com.android.systemui.navigationbar.car.CarFacetButton
+ <com.android.systemui.navigationbar.car.CarNavigationButton
android:id="@+id/home"
android:layout_width="@*android:dimen/car_touch_target_size"
android:layout_height="match_parent"
@@ -39,7 +39,8 @@
systemui:icon="@drawable/car_ic_overview"
systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
systemui:selectedIcon="@drawable/car_ic_overview_selected"
- systemui:useMoreIcon="false"/>
+ systemui:highlightWhenSelected="true"
+ />
</LinearLayout>
</com.android.systemui.navigationbar.car.CarNavigationBarView>
diff --git a/packages/CarSystemUI/res/layout/car_navigation_button.xml b/packages/CarSystemUI/res/layout/car_navigation_button.xml
index 6d8cca9..bafbb64 100644
--- a/packages/CarSystemUI/res/layout/car_navigation_button.xml
+++ b/packages/CarSystemUI/res/layout/car_navigation_button.xml
@@ -18,12 +18,34 @@
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <com.android.keyguard.AlphaOptimizedImageButton
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/car_nav_button_icon"
- android:layout_height="wrap_content"
- android:layout_width="@dimen/car_navigation_button_width"
- android:layout_centerInParent="true"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="center"
android:animateLayoutChanges="true"
- android:scaleType="fitCenter">
- </com.android.keyguard.AlphaOptimizedImageButton>
+ android:orientation="vertical">
+
+ <com.android.keyguard.AlphaOptimizedImageButton
+ android:id="@+id/car_nav_button_icon_image"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:animateLayoutChanges="true"
+ android:background="@android:color/transparent"
+ android:scaleType="fitCenter">
+ </com.android.keyguard.AlphaOptimizedImageButton>
+
+ <com.android.keyguard.AlphaOptimizedImageButton
+ android:id="@+id/car_nav_button_more_icon"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:animateLayoutChanges="true"
+ android:src="@drawable/car_ic_arrow"
+ android:background="@android:color/transparent"
+ android:scaleType="fitCenter">
+ </com.android.keyguard.AlphaOptimizedImageButton>
+
+ </LinearLayout>
</merge>
diff --git a/packages/CarSystemUI/res/values/attrs.xml b/packages/CarSystemUI/res/values/attrs.xml
index 6178738..54026af 100644
--- a/packages/CarSystemUI/res/values/attrs.xml
+++ b/packages/CarSystemUI/res/values/attrs.xml
@@ -16,6 +16,12 @@
-->
<resources>
+ <attr name="icon" format="reference"/>
+ <attr name="selectedIcon" format="reference"/>
+ <attr name="intent" format="string"/>
+ <attr name="longIntent" format="string"/>
+ <attr name="selectedAlpha" format="float" />
+ <attr name="unselectedAlpha" format="float" />
<!-- Custom attributes to configure hvac values -->
<declare-styleable name="AnimatedTemperatureView">
@@ -32,4 +38,67 @@
<attr name="android:minEms"/>
<attr name="android:textAppearance"/>
</declare-styleable>
+
+ <!-- Allow for custom attribs to be added to a nav button -->
+ <declare-styleable name="CarNavigationButton">
+ <!-- intent to start when button is click -->
+ <attr name="intent" />
+ <!-- intent to start when a long press has happened -->
+ <attr name="longIntent" />
+ <!-- start the intent as a broad cast instead of an activity if true-->
+ <attr name="broadcast" format="boolean"/>
+ <!-- Alpha value to used when in selected state. Defaults 1f -->
+ <attr name="selectedAlpha" />
+ <!-- Alpha value to used when in un-selected state. Defaults 0.7f -->
+ <attr name="unselectedAlpha" />
+ <!-- icon to be rendered when in selected state -->
+ <attr name="selectedIcon" />
+ <!-- icon to be rendered (drawable) -->
+ <attr name="icon"/>
+ <!-- categories that will be added as extras to the fired intents -->
+ <attr name="categories" format="string"/>
+ <!-- package names that will be added as extras to the fired intents -->
+ <attr name="packages" format="string" />
+ <!-- componentName names that will be used for detecting selected state -->
+ <attr name="componentNames" format="string" />
+ <!-- whether to highlight the button when selected. Defaults false -->
+ <attr name="showMoreWhenSelected" format="boolean" />
+ <!-- whether to highlight the button when selected. Defaults false -->
+ <attr name="highlightWhenSelected" format="boolean" />
+ </declare-styleable>
+
+ <!-- Custom attributes to configure hvac values -->
+ <declare-styleable name="TemperatureView">
+ <attr name="hvacAreaId" format="integer"/>
+ <attr name="hvacPropertyId" format="integer"/>
+ <attr name="hvacTempFormat" format="string"/>
+ </declare-styleable>
+
+ <declare-styleable name="carVolumeItems"/>
+ <declare-styleable name="carVolumeItems_item">
+ <!-- Align with AudioAttributes.USAGE_* -->
+ <attr name="usage">
+ <enum name="unknown" value="0"/>
+ <enum name="media" value="1"/>
+ <enum name="voice_communication" value="2"/>
+ <enum name="voice_communication_signalling" value="3"/>
+ <enum name="alarm" value="4"/>
+ <enum name="notification" value="5"/>
+ <enum name="notification_ringtone" value="6"/>
+ <enum name="notification_communication_request" value="7"/>
+ <enum name="notification_communication_instant" value="8"/>
+ <enum name="notification_communication_delayed" value="9"/>
+ <enum name="notification_event" value="10"/>
+ <enum name="assistance_accessibility" value="11"/>
+ <enum name="assistance_navigation_guidance" value="12"/>
+ <enum name="assistance_sonification" value="13"/>
+ <enum name="game" value="14"/>
+ <!-- hidden, do not use -->
+ <!-- enum name="virtual_source" value="15"/ -->
+ <enum name="assistant" value="16"/>
+ </attr>
+
+ <!-- Icon resource ids to render on UI -->
+ <attr name="icon" />
+ </declare-styleable>
</resources>
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/AssitantButton.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/AssitantButton.java
index c50de22..98cc00e 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/AssitantButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/AssitantButton.java
@@ -30,9 +30,9 @@
/**
* AssitantButton is a ui component that will trigger the Voice Interaction Service.
*/
-public class AssitantButton extends CarFacetButton {
+public class AssitantButton extends CarNavigationButton {
- private static final String TAG = "CarFacetButton";
+ private static final String TAG = "AssistantButton";
private final AssistUtils mAssistUtils;
private IVoiceInteractionSessionShowCallback mShowCallback =
new IVoiceInteractionSessionShowCallback.Stub() {
@@ -62,7 +62,7 @@
}
@Override
- protected void setupIntents(TypedArray typedArray) {
+ protected void setUpIntents(TypedArray typedArray) {
// left blank because for the assistant button Intent will not be passed from the layout.
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/ButtonSelectionStateController.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/ButtonSelectionStateController.java
new file mode 100644
index 0000000..c36aaa0
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/ButtonSelectionStateController.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.navigationbar.car;
+
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.view.Display;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * CarNavigationButtons can optionally have selection state that toggles certain visual indications
+ * based on whether the active application on screen is associated with it. This is basically a
+ * similar concept to a radio button group.
+ *
+ * This class controls the selection state of CarNavigationButtons that have opted in to have such
+ * selection state-dependent visual indications.
+ */
+@Singleton
+public class ButtonSelectionStateController {
+
+ private final Set<CarNavigationButton> mRegisteredViews = new HashSet<>();
+
+ protected ButtonMap mButtonsByCategory = new ButtonMap();
+ protected ButtonMap mButtonsByPackage = new ButtonMap();
+ protected ButtonMap mButtonsByComponentName = new ButtonMap();
+ protected HashSet<CarNavigationButton> mSelectedButtons;
+ protected Context mContext;
+
+ @Inject
+ public ButtonSelectionStateController(Context context) {
+ mContext = context;
+ mSelectedButtons = new HashSet<>();
+ }
+
+ /**
+ * Iterate through a view looking for CarNavigationButton and add it to the controller if it
+ * opted in to be highlighted when the active application is associated with it.
+ *
+ * @param v the View that may contain CarFacetButtons
+ */
+ protected void addAllButtonsWithSelectionState(View v) {
+ if (v instanceof CarNavigationButton) {
+ if (((CarNavigationButton) v).hasSelectionState()) {
+ addButtonWithSelectionState((CarNavigationButton) v);
+ }
+ } else if (v instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) v;
+ for (int i = 0; i < viewGroup.getChildCount(); i++) {
+ addAllButtonsWithSelectionState(viewGroup.getChildAt(i));
+ }
+ }
+ }
+
+ /** Removes all buttons from the button maps. */
+ protected void removeAll() {
+ mButtonsByCategory.clear();
+ mButtonsByPackage.clear();
+ mButtonsByComponentName.clear();
+ mSelectedButtons.clear();
+ mRegisteredViews.clear();
+ }
+
+ /**
+ * This will unselect the currently selected CarNavigationButton and determine which one should
+ * be selected next. It does this by reading the properties on the CarNavigationButton and
+ * seeing if they are a match with the supplied StackInfo list.
+ * The order of selection detection is ComponentName, PackageName then Category
+ * They will then be compared with the supplied StackInfo list.
+ * The StackInfo is expected to be supplied in order of recency and StackInfo will only be used
+ * for consideration if it has the same displayId as the CarNavigationButton.
+ *
+ * @param stackInfoList of the currently running application
+ * @param validDisplay index of the valid display
+ */
+
+ protected void taskChanged(List<ActivityManager.StackInfo> stackInfoList, int validDisplay) {
+ ActivityManager.StackInfo validStackInfo = null;
+ for (ActivityManager.StackInfo stackInfo : stackInfoList) {
+ // Find the first stack info with a topActivity in the primary display.
+ // TODO: We assume that CarFacetButton will launch an app only in the primary display.
+ // We need to extend the functionality to handle the multiple display properly.
+ if (stackInfo.topActivity != null && stackInfo.displayId == validDisplay) {
+ validStackInfo = stackInfo;
+ break;
+ }
+ }
+
+ if (validStackInfo == null) {
+ // No stack was found that was on the same display as the buttons thus return
+ return;
+ }
+ int displayId = validStackInfo.displayId;
+
+ mSelectedButtons.forEach(carNavigationButton -> {
+ if (carNavigationButton.getDisplayId() == displayId) {
+ carNavigationButton.setSelected(false);
+ }
+ });
+ mSelectedButtons.clear();
+
+ HashSet<CarNavigationButton> selectedButtons = findSelectedButtons(validStackInfo);
+
+ if (selectedButtons != null) {
+ selectedButtons.forEach(carNavigationButton -> {
+ if (carNavigationButton.getDisplayId() == displayId) {
+ carNavigationButton.setSelected(true);
+ mSelectedButtons.add(carNavigationButton);
+ }
+ });
+ }
+ }
+
+ /**
+ * Defaults to Display.DEFAULT_DISPLAY when no parameter is provided for the validDisplay.
+ *
+ * @param stackInfoList
+ */
+ protected void taskChanged(List<ActivityManager.StackInfo> stackInfoList) {
+ taskChanged(stackInfoList, Display.DEFAULT_DISPLAY);
+ }
+
+ /**
+ * Add navigation button to this controller if it uses selection state.
+ */
+ private void addButtonWithSelectionState(CarNavigationButton carNavigationButton) {
+ if (mRegisteredViews.contains(carNavigationButton)) {
+ return;
+ }
+ String[] categories = carNavigationButton.getCategories();
+ for (int i = 0; i < categories.length; i++) {
+ mButtonsByCategory.add(categories[i], carNavigationButton);
+ }
+
+ String[] packages = carNavigationButton.getPackages();
+ for (int i = 0; i < packages.length; i++) {
+ mButtonsByPackage.add(packages[i], carNavigationButton);
+ }
+ String[] componentNames = carNavigationButton.getComponentName();
+ for (int i = 0; i < componentNames.length; i++) {
+ mButtonsByComponentName.add(componentNames[i], carNavigationButton);
+ }
+
+ mRegisteredViews.add(carNavigationButton);
+ }
+
+ private HashSet<CarNavigationButton> findSelectedButtons(
+ ActivityManager.StackInfo validStackInfo) {
+ String packageName = validStackInfo.topActivity.getPackageName();
+
+ HashSet<CarNavigationButton> selectedButtons =
+ findButtonsByComponentName(validStackInfo.topActivity);
+ if (selectedButtons == null) {
+ selectedButtons = mButtonsByPackage.get(packageName);
+ }
+ if (selectedButtons == null) {
+ String category = getPackageCategory(packageName);
+ if (category != null) {
+ selectedButtons = mButtonsByCategory.get(category);
+ }
+ }
+
+ return selectedButtons;
+ }
+
+ private HashSet<CarNavigationButton> findButtonsByComponentName(
+ ComponentName componentName) {
+ HashSet<CarNavigationButton> buttons =
+ mButtonsByComponentName.get(componentName.flattenToShortString());
+ return (buttons != null) ? buttons :
+ mButtonsByComponentName.get(componentName.flattenToString());
+ }
+
+ private String getPackageCategory(String packageName) {
+ PackageManager pm = mContext.getPackageManager();
+ Set<String> supportedCategories = mButtonsByCategory.keySet();
+ for (String category : supportedCategories) {
+ Intent intent = new Intent();
+ intent.setPackage(packageName);
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.addCategory(category);
+ List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
+ if (list.size() > 0) {
+ // Cache this package name into ButtonsByPackage map, so we won't have to query
+ // all categories next time this package name shows up.
+ mButtonsByPackage.put(packageName, mButtonsByCategory.get(category));
+ return category;
+ }
+ }
+ return null;
+ }
+
+ // simple multi-map
+ private static class ButtonMap extends HashMap<String, HashSet<CarNavigationButton>> {
+
+ public boolean add(String key, CarNavigationButton value) {
+ if (containsKey(key)) {
+ return get(key).add(value);
+ }
+ HashSet<CarNavigationButton> set = new HashSet<>();
+ set.add(value);
+ put(key, set);
+ return true;
+ }
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/FacetButtonTaskStackListener.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/ButtonSelectionStateListener.java
similarity index 75%
rename from packages/CarSystemUI/src/com/android/systemui/navigationbar/car/FacetButtonTaskStackListener.java
rename to packages/CarSystemUI/src/com/android/systemui/navigationbar/car/ButtonSelectionStateListener.java
index 4925220..9da4121 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/FacetButtonTaskStackListener.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/ButtonSelectionStateListener.java
@@ -24,28 +24,25 @@
import javax.inject.Inject;
import javax.inject.Singleton;
-import dagger.Lazy;
-
/**
* An implementation of TaskStackChangeListener, that listens for changes in the system
* task stack and notifies the navigation bar.
*/
@Singleton
-class FacetButtonTaskStackListener extends TaskStackChangeListener {
- private static final String TAG = FacetButtonTaskStackListener.class.getSimpleName();
+class ButtonSelectionStateListener extends TaskStackChangeListener {
+ private static final String TAG = ButtonSelectionStateListener.class.getSimpleName();
- private final Lazy<CarFacetButtonController> mFacetButtonControllerLazy;
+ private final ButtonSelectionStateController mButtonSelectionStateController;
@Inject
- FacetButtonTaskStackListener(
- Lazy<CarFacetButtonController> carFacetButtonControllerLazy) {
- mFacetButtonControllerLazy = carFacetButtonControllerLazy;
+ ButtonSelectionStateListener(ButtonSelectionStateController carNavigationButtonController) {
+ mButtonSelectionStateController = carNavigationButtonController;
}
@Override
public void onTaskStackChanged() {
try {
- mFacetButtonControllerLazy.get().taskChanged(
+ mButtonSelectionStateController.taskChanged(
ActivityTaskManager.getService().getAllStackInfos());
} catch (Exception e) {
Log.e(TAG, "Getting StackInfo from activity manager failed", e);
@@ -55,7 +52,7 @@
@Override
public void onTaskDisplayChanged(int taskId, int newDisplayId) {
try {
- mFacetButtonControllerLazy.get().taskChanged(
+ mButtonSelectionStateController.taskChanged(
ActivityTaskManager.getService().getAllStackInfos());
} catch (Exception e) {
Log.e(TAG, "Getting StackInfo from activity manager failed", e);
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarFacetButton.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarFacetButton.java
deleted file mode 100644
index 0b89992..0000000
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarFacetButton.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.navigationbar.car;
-
-import android.app.ActivityOptions;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.TypedArray;
-import android.os.Build;
-import android.os.UserHandle;
-import android.util.AttributeSet;
-import android.view.Display;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-
-import com.android.keyguard.AlphaOptimizedImageButton;
-import com.android.systemui.R;
-
-/**
- * CarFacetButton is a ui component designed to be used as a shortcut for an app of a defined
- * category. It can also render a indicator implying that there are more options of apps to launch
- * using this component. This is done with a "More icon" currently an arrow as defined in the layout
- * file. The class is to serve as an example.
- *
- * New activity will be launched on the same display as the button is on.
- * Usage example: A button that allows a user to select a music app and indicate that there are
- * other music apps installed.
- */
-public class CarFacetButton extends LinearLayout {
- private static final String FACET_FILTER_DELIMITER = ";";
- /**
- * Extra information to be sent to a helper to make the decision of what app to launch when
- * clicked.
- */
- private static final String EXTRA_FACET_CATEGORIES = "categories";
- private static final String EXTRA_FACET_PACKAGES = "packages";
- private static final String EXTRA_FACET_ID = "filter_id";
- private static final String EXTRA_FACET_LAUNCH_PICKER = "launch_picker";
- private static final String TAG = "CarFacetButton";
-
- private Context mContext;
- private AlphaOptimizedImageButton mIcon;
- private AlphaOptimizedImageButton mMoreIcon;
- private boolean mSelected = false;
- private String[] mComponentNames;
- /** App categories that are to be used with this widget */
- private String[] mFacetCategories;
- /** App packages that are allowed to be used with this widget */
- private String[] mFacetPackages;
- private int mIconResourceId;
- /**
- * If defined in the xml this will be the icon that's rendered when the button is marked as
- * selected
- */
- private int mSelectedIconResourceId;
- private boolean mUseMoreIcon = true;
- private float mSelectedAlpha = 1f;
- private float mUnselectedAlpha = 1f;
-
- public CarFacetButton(Context context, AttributeSet attrs) {
- super(context, attrs);
- mContext = context;
- View.inflate(context, R.layout.car_facet_button, this);
- // extract custom attributes
- TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarFacetButton);
- setupIntents(typedArray);
- setupIcons(typedArray);
- }
-
- /**
- * Reads the custom attributes to setup click handlers for this component.
- */
- protected void setupIntents(TypedArray typedArray) {
- String intentString = typedArray.getString(R.styleable.CarFacetButton_intent);
- String longPressIntentString = typedArray.getString(R.styleable.CarFacetButton_longIntent);
- String categoryString = typedArray.getString(R.styleable.CarFacetButton_categories);
- String packageString = typedArray.getString(R.styleable.CarFacetButton_packages);
- String componentNameString =
- typedArray.getString(R.styleable.CarFacetButton_componentNames);
- try {
- final Intent intent = Intent.parseUri(intentString, Intent.URI_INTENT_SCHEME);
- intent.putExtra(EXTRA_FACET_ID, Integer.toString(getId()));
-
- if (packageString != null) {
- mFacetPackages = packageString.split(FACET_FILTER_DELIMITER);
- intent.putExtra(EXTRA_FACET_PACKAGES, mFacetPackages);
- }
- if (categoryString != null) {
- mFacetCategories = categoryString.split(FACET_FILTER_DELIMITER);
- intent.putExtra(EXTRA_FACET_CATEGORIES, mFacetCategories);
- }
- if (componentNameString != null) {
- mComponentNames = componentNameString.split(FACET_FILTER_DELIMITER);
- }
-
- setOnClickListener(v -> {
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchDisplayId(mContext.getDisplayId());
- intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, mSelected);
- mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
- mContext.sendBroadcastAsUser(
- new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), UserHandle.CURRENT);
- });
-
- if (longPressIntentString != null && (Build.IS_ENG || Build.IS_USERDEBUG)) {
- final Intent longPressIntent = Intent.parseUri(longPressIntentString,
- Intent.URI_INTENT_SCHEME);
- setOnLongClickListener(v -> {
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchDisplayId(mContext.getDisplayId());
- mContext.startActivityAsUser(longPressIntent, options.toBundle(),
- UserHandle.CURRENT);
- mContext.sendBroadcastAsUser(
- new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), UserHandle.CURRENT);
- return true;
- });
- }
- } catch (Exception e) {
- throw new RuntimeException("Failed to attach intent", e);
- }
- }
-
- private void setupIcons(TypedArray styledAttributes) {
- mSelectedAlpha = styledAttributes.getFloat(
- R.styleable.CarFacetButton_selectedAlpha, mSelectedAlpha);
- mUnselectedAlpha = styledAttributes.getFloat(
- R.styleable.CarFacetButton_unselectedAlpha, mUnselectedAlpha);
- mIcon = findViewById(R.id.car_nav_button_icon);
- mIcon.setScaleType(ImageView.ScaleType.CENTER);
- mIcon.setClickable(false);
- mIcon.setAlpha(mUnselectedAlpha);
- mIconResourceId = styledAttributes.getResourceId(R.styleable.CarFacetButton_icon, 0);
- mIcon.setImageResource(mIconResourceId);
- mSelectedIconResourceId = styledAttributes.getResourceId(
- R.styleable.CarFacetButton_selectedIcon, mIconResourceId);
-
- mMoreIcon = findViewById(R.id.car_nav_button_more_icon);
- mMoreIcon.setClickable(false);
- mMoreIcon.setAlpha(mSelectedAlpha);
- mMoreIcon.setVisibility(GONE);
- mUseMoreIcon = styledAttributes.getBoolean(R.styleable.CarFacetButton_useMoreIcon, true);
- }
-
- /**
- * @return The app categories the component represents
- */
- public String[] getCategories() {
- if (mFacetCategories == null) {
- return new String[0];
- }
- return mFacetCategories;
- }
-
- /**
- * @return The valid packages that should be considered.
- */
- public String[] getFacetPackages() {
- if (mFacetPackages == null) {
- return new String[0];
- }
- return mFacetPackages;
- }
-
- /**
- * @return The list of component names.
- */
- public String[] getComponentName() {
- if (mComponentNames == null) {
- return new String[0];
- }
- return mComponentNames;
- }
-
- /**
- * Updates the alpha of the icons to "selected" and shows the "More icon"
- *
- * @param selected true if the view must be selected, false otherwise
- */
- public void setSelected(boolean selected) {
- super.setSelected(selected);
- setSelected(selected, selected);
- }
-
- /**
- * Updates the visual state to let the user know if it's been selected.
- *
- * @param selected true if should update the alpha of the icon to selected, false otherwise
- * @param showMoreIcon true if the "more icon" should be shown, false otherwise. Note this
- * is ignored if the attribute useMoreIcon is set to false
- */
- public void setSelected(boolean selected, boolean showMoreIcon) {
- mSelected = selected;
- mIcon.setAlpha(mSelected ? mSelectedAlpha : mUnselectedAlpha);
- mIcon.setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId);
- if (mUseMoreIcon) {
- mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE);
- }
- }
-
- /**
- * @return The id of the display the button is on or Display.INVALID_DISPLAY if it's not yet on
- * a display.
- */
- public int getDisplayId() {
- Display display = getDisplay();
- if (display == null) {
- return Display.INVALID_DISPLAY;
- }
- return display.getDisplayId();
- }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarFacetButtonController.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarFacetButtonController.java
deleted file mode 100644
index f66e828..0000000
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarFacetButtonController.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.navigationbar.car;
-
-import android.app.ActivityManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.view.Display;
-import android.view.View;
-import android.view.ViewGroup;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
-/**
- * CarFacetButtons placed on the nav bar are designed to have visual indication that the active
- * application on screen is associated with it. This is basically a similar concept to a radio
- * button group.
- */
-@Singleton
-public class CarFacetButtonController {
-
- private final Set<CarFacetButton> mRegisteredViews = new HashSet<>();
-
- protected ButtonMap mButtonsByCategory = new ButtonMap();
- protected ButtonMap mButtonsByPackage = new ButtonMap();
- protected ButtonMap mButtonsByComponentName = new ButtonMap();
- protected HashSet<CarFacetButton> mSelectedFacetButtons;
- protected Context mContext;
-
- @Inject
- public CarFacetButtonController(Context context) {
- mContext = context;
- mSelectedFacetButtons = new HashSet<>();
- }
-
- /**
- * Add facet button to this controller. The expected use is for the facet button
- * to get a reference to this controller via {@link com.android.systemui.Dependency}
- * and self add.
- */
- private void addFacetButton(CarFacetButton facetButton) {
- if (mRegisteredViews.contains(facetButton)) {
- return;
- }
-
- String[] categories = facetButton.getCategories();
- for (int i = 0; i < categories.length; i++) {
- mButtonsByCategory.add(categories[i], facetButton);
- }
-
- String[] facetPackages = facetButton.getFacetPackages();
- for (int i = 0; i < facetPackages.length; i++) {
- mButtonsByPackage.add(facetPackages[i], facetButton);
- }
- String[] componentNames = facetButton.getComponentName();
- for (int i = 0; i < componentNames.length; i++) {
- mButtonsByComponentName.add(componentNames[i], facetButton);
- }
-
- mRegisteredViews.add(facetButton);
- }
-
- /** Removes all buttons from the button maps. */
- public void removeAll() {
- mButtonsByCategory.clear();
- mButtonsByPackage.clear();
- mButtonsByComponentName.clear();
- mSelectedFacetButtons.clear();
- mRegisteredViews.clear();
- }
-
- /**
- * Iterate through a view looking for CarFacetButtons and adding them to the controller if found
- *
- * @param v the View that may contain CarFacetButtons
- */
- public void addAllFacetButtons(View v) {
- if (v instanceof CarFacetButton) {
- addFacetButton((CarFacetButton) v);
- } else if (v instanceof ViewGroup) {
- ViewGroup viewGroup = (ViewGroup) v;
- for (int i = 0; i < viewGroup.getChildCount(); i++) {
- addAllFacetButtons(viewGroup.getChildAt(i));
- }
- }
- }
-
- /**
- * This will unselect the currently selected CarFacetButton and determine which one should be
- * selected next. It does this by reading the properties on the CarFacetButton and seeing if
- * they are a match with the supplied StackInfo list.
- * The order of selection detection is ComponentName, PackageName then Category
- * They will then be compared with the supplied StackInfo list.
- * The StackInfo is expected to be supplied in order of recency and StackInfo will only be used
- * for consideration if it has the same displayId as the CarFacetButtons.
- *
- * @param stackInfoList of the currently running application
- */
- public void taskChanged(List<ActivityManager.StackInfo> stackInfoList) {
- ActivityManager.StackInfo validStackInfo = null;
- for (ActivityManager.StackInfo stackInfo : stackInfoList) {
- // Find the first stack info with a topActivity in the primary display.
- // TODO: We assume that CarFacetButton will launch an app only in the primary display.
- // We need to extend the functionality to handle the mutliple display properly.
- if (stackInfo.topActivity != null && stackInfo.displayId == Display.DEFAULT_DISPLAY) {
- validStackInfo = stackInfo;
- break;
- }
- }
-
- if (validStackInfo == null) {
- // No stack was found that was on the same display as the facet buttons thus return
- return;
- }
-
- if (mSelectedFacetButtons != null) {
- Iterator<CarFacetButton> iterator = mSelectedFacetButtons.iterator();
- while (iterator.hasNext()) {
- CarFacetButton carFacetButton = iterator.next();
- if (carFacetButton.getDisplayId() == validStackInfo.displayId) {
- carFacetButton.setSelected(false);
- iterator.remove();
- }
- }
- }
-
- String packageName = validStackInfo.topActivity.getPackageName();
- HashSet<CarFacetButton> facetButton =
- findFacetButtonByComponentName(validStackInfo.topActivity);
- if (facetButton == null) {
- facetButton = mButtonsByPackage.get(packageName);
- }
-
- if (facetButton == null) {
- String category = getPackageCategory(packageName);
- if (category != null) {
- facetButton = mButtonsByCategory.get(category);
- }
- }
-
- if (facetButton != null) {
- for (CarFacetButton carFacetButton : facetButton) {
- if (carFacetButton.getDisplayId() == validStackInfo.displayId) {
- carFacetButton.setSelected(true);
- mSelectedFacetButtons.add(carFacetButton);
- }
- }
- }
-
- }
-
- private HashSet<CarFacetButton> findFacetButtonByComponentName(ComponentName componentName) {
- HashSet<CarFacetButton> buttons =
- mButtonsByComponentName.get(componentName.flattenToShortString());
- return (buttons != null) ? buttons :
- mButtonsByComponentName.get(componentName.flattenToString());
- }
-
- protected String getPackageCategory(String packageName) {
- PackageManager pm = mContext.getPackageManager();
- Set<String> supportedCategories = mButtonsByCategory.keySet();
- for (String category : supportedCategories) {
- Intent intent = new Intent();
- intent.setPackage(packageName);
- intent.setAction(Intent.ACTION_MAIN);
- intent.addCategory(category);
- List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
- if (list.size() > 0) {
- // Cache this package name into facetPackageMap, so we won't have to query
- // all categories next time this package name shows up.
- mButtonsByPackage.put(packageName, mButtonsByCategory.get(category));
- return category;
- }
- }
- return null;
- }
-
- // simple multi-map
- private static class ButtonMap extends HashMap<String, HashSet<CarFacetButton>> {
-
- public boolean add(String key, CarFacetButton value) {
- if (containsKey(key)) {
- return get(key).add(value);
- }
- HashSet<CarFacetButton> set = new HashSet<>();
- set.add(value);
- put(key, set);
- return true;
- }
- }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
index 59a084e..d8c9d17 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
@@ -57,12 +57,12 @@
private final WindowManager mWindowManager;
private final CarDeviceProvisionedController mCarDeviceProvisionedController;
private final CommandQueue mCommandQueue;
- private final Lazy<FacetButtonTaskStackListener> mFacetButtonTaskStackListenerLazy;
+ private final ButtonSelectionStateListener mButtonSelectionStateListener;
private final Handler mMainHandler;
private final Lazy<KeyguardStateController> mKeyguardStateControllerLazy;
private final Lazy<NavigationBarController> mNavigationBarControllerLazy;
private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
- private final Lazy<CarFacetButtonController> mCarFacetButtonControllerLazy;
+ private final ButtonSelectionStateController mButtonSelectionStateController;
private IStatusBarService mBarService;
private ActivityManagerWrapper mActivityManagerWrapper;
@@ -92,24 +92,24 @@
WindowManager windowManager,
DeviceProvisionedController deviceProvisionedController,
CommandQueue commandQueue,
- Lazy<FacetButtonTaskStackListener> facetButtonTaskStackListenerLazy,
+ ButtonSelectionStateListener buttonSelectionStateListener,
@Main Handler mainHandler,
Lazy<KeyguardStateController> keyguardStateControllerLazy,
Lazy<NavigationBarController> navigationBarControllerLazy,
SuperStatusBarViewFactory superStatusBarViewFactory,
- Lazy<CarFacetButtonController> carFacetButtonControllerLazy) {
+ ButtonSelectionStateController buttonSelectionStateController) {
super(context);
mCarNavigationBarController = carNavigationBarController;
mWindowManager = windowManager;
mCarDeviceProvisionedController = (CarDeviceProvisionedController)
deviceProvisionedController;
mCommandQueue = commandQueue;
- mFacetButtonTaskStackListenerLazy = facetButtonTaskStackListenerLazy;
+ mButtonSelectionStateListener = buttonSelectionStateListener;
mMainHandler = mainHandler;
mKeyguardStateControllerLazy = keyguardStateControllerLazy;
mNavigationBarControllerLazy = navigationBarControllerLazy;
mSuperStatusBarViewFactory = superStatusBarViewFactory;
- mCarFacetButtonControllerLazy = carFacetButtonControllerLazy;
+ mButtonSelectionStateController = buttonSelectionStateController;
}
@Override
@@ -156,7 +156,7 @@
createNavigationBar(result);
mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
- mActivityManagerWrapper.registerTaskStackListener(mFacetButtonTaskStackListenerLazy.get());
+ mActivityManagerWrapper.registerTaskStackListener(mButtonSelectionStateListener);
mCarNavigationBarController.connectToHvac();
}
@@ -181,7 +181,7 @@
// remove and reattach all hvac components such that we don't keep a reference to unused
// ui elements
mCarNavigationBarController.removeAllFromHvac();
- mCarFacetButtonControllerLazy.get().removeAll();
+ mButtonSelectionStateController.removeAll();
if (mTopNavigationBarWindow != null) {
mTopNavigationBarWindow.removeAllViews();
@@ -343,7 +343,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.print(" mTaskStackListener=");
- pw.println(mFacetButtonTaskStackListenerLazy.get());
+ pw.println(mButtonSelectionStateListener);
pw.print(" mBottomNavigationBarView=");
pw.println(mBottomNavigationBarView);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarController.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarController.java
index 6f28843..a56c4ed 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarController.java
@@ -37,7 +37,7 @@
private final Context mContext;
private final NavigationBarViewFactory mNavigationBarViewFactory;
- private final Lazy<CarFacetButtonController> mCarFacetButtonControllerLazy;
+ private final ButtonSelectionStateController mButtonSelectionStateController;
private final Lazy<HvacController> mHvacControllerLazy;
private boolean mShowBottom;
@@ -58,11 +58,11 @@
@Inject
public CarNavigationBarController(Context context,
NavigationBarViewFactory navigationBarViewFactory,
- Lazy<CarFacetButtonController> carFacetButtonControllerLazy,
+ ButtonSelectionStateController buttonSelectionStateController,
Lazy<HvacController> hvacControllerLazy) {
mContext = context;
mNavigationBarViewFactory = navigationBarViewFactory;
- mCarFacetButtonControllerLazy = carFacetButtonControllerLazy;
+ mButtonSelectionStateController = buttonSelectionStateController;
mHvacControllerLazy = hvacControllerLazy;
// Read configuration.
@@ -175,7 +175,7 @@
NotificationsShadeController notifShadeController) {
view.setStatusBarWindowTouchListener(statusBarTouchListener);
view.setNotificationsPanelController(notifShadeController);
- mCarFacetButtonControllerLazy.get().addAllFacetButtons(view);
+ mButtonSelectionStateController.addAllButtonsWithSelectionState(view);
mHvacControllerLazy.get().addTemperatureViewToController(view);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationButton.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationButton.java
index 922bfff..d08fbbc 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationButton.java
@@ -24,8 +24,12 @@
import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.Display;
+import android.view.View;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import com.android.keyguard.AlphaOptimizedImageButton;
import com.android.systemui.R;
import java.net.URISyntaxException;
@@ -35,110 +39,66 @@
* xml file level. This allows for more control via overlays instead of having to update
* code.
*/
-public class CarNavigationButton extends com.android.keyguard.AlphaOptimizedImageButton {
- private static final String TAG = "CarNavigationButton";
+public class CarNavigationButton extends LinearLayout {
+ protected static final float DEFAULT_SELECTED_ALPHA = 1f;
+ protected static final float DEFAULT_UNSELECTED_ALPHA = 0.75f;
+
+ private static final String TAG = "CarNavigationButton";
+ private static final String BUTTON_FILTER_DELIMITER = ";";
+ private static final String EXTRA_BUTTON_CATEGORIES = "categories";
+ private static final String EXTRA_BUTTON_PACKAGES = "packages";
private static final int UNSEEN_ICON_RESOURCE_ID = R.drawable.car_ic_notification_unseen;
private static final int UNSEEN_SELECTED_ICON_RESOURCE_ID =
R.drawable.car_ic_notification_selected_unseen;
private Context mContext;
+ private AlphaOptimizedImageButton mIcon;
+ private AlphaOptimizedImageButton mMoreIcon;
private String mIntent;
private String mLongIntent;
private boolean mBroadcastIntent;
private boolean mHasUnseen = false;
private boolean mSelected = false;
- private float mSelectedAlpha = 1f;
- private float mUnselectedAlpha = 1f;
+ private float mSelectedAlpha;
+ private float mUnselectedAlpha;
private int mSelectedIconResourceId;
private int mIconResourceId;
-
+ private String[] mComponentNames;
+ /** App categories that are to be used with this widget */
+ private String[] mButtonCategories;
+ /** App packages that are allowed to be used with this widget */
+ private String[] mButtonPackages;
+ /** Whether to display more icon beneath the primary icon when the button is selected */
+ private boolean mShowMoreWhenSelected = false;
+ /** Whether to highlight the button if the active application is associated with it */
+ private boolean mHighlightWhenSelected = false;
public CarNavigationButton(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
-
+ View.inflate(mContext, R.layout.car_navigation_button, /* root= */ this);
// CarNavigationButton attrs
- TypedArray typedArray = context.obtainStyledAttributes(
- attrs, R.styleable.CarNavigationButton);
- mIntent = typedArray.getString(R.styleable.CarNavigationButton_intent);
- mLongIntent = typedArray.getString(R.styleable.CarNavigationButton_longIntent);
- mBroadcastIntent = typedArray.getBoolean(R.styleable.CarNavigationButton_broadcast, false);
- mSelectedAlpha = typedArray.getFloat(
- R.styleable.CarNavigationButton_selectedAlpha, mSelectedAlpha);
- mUnselectedAlpha = typedArray.getFloat(
- R.styleable.CarNavigationButton_unselectedAlpha, mUnselectedAlpha);
- mSelectedIconResourceId = typedArray.getResourceId(
- R.styleable.CarNavigationButton_selectedIcon, mIconResourceId);
- mIconResourceId = typedArray.getResourceId(
- R.styleable.CarNavigationButton_icon, 0);
+ TypedArray typedArray = context.obtainStyledAttributes(attrs,
+ R.styleable.CarNavigationButton);
+
+ setUpIntents(typedArray);
+ setUpIcons(typedArray);
typedArray.recycle();
}
-
- /**
- * After the standard inflate this then adds the xml defined intents to click and long click
- * actions if defined.
- */
- @Override
- public void onFinishInflate() {
- super.onFinishInflate();
- setScaleType(ImageView.ScaleType.CENTER);
- setAlpha(mUnselectedAlpha);
- setImageResource(mIconResourceId);
- try {
- if (mIntent != null) {
- final Intent intent = Intent.parseUri(mIntent, Intent.URI_INTENT_SCHEME);
- setOnClickListener(v -> {
- try {
- if (mBroadcastIntent) {
- mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
- mContext.sendBroadcastAsUser(
- new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS),
- UserHandle.CURRENT);
- return;
- }
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchDisplayId(mContext.getDisplayId());
- mContext.startActivityAsUser(intent, options.toBundle(),
- UserHandle.CURRENT);
- } catch (Exception e) {
- Log.e(TAG, "Failed to launch intent", e);
- }
- });
- }
- } catch (URISyntaxException e) {
- throw new RuntimeException("Failed to attach intent", e);
- }
-
- try {
- if (mLongIntent != null && (Build.IS_ENG || Build.IS_USERDEBUG)) {
- final Intent intent = Intent.parseUri(mLongIntent, Intent.URI_INTENT_SCHEME);
- setOnLongClickListener(v -> {
- try {
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchDisplayId(mContext.getDisplayId());
- mContext.startActivityAsUser(intent, options.toBundle(),
- UserHandle.CURRENT);
- } catch (Exception e) {
- Log.e(TAG, "Failed to launch intent", e);
- }
- // consume event either way
- return true;
- });
- }
- } catch (URISyntaxException e) {
- throw new RuntimeException("Failed to attach long press intent", e);
- }
- }
-
/**
* @param selected true if should indicate if this is a selected state, false otherwise
*/
public void setSelected(boolean selected) {
super.setSelected(selected);
mSelected = selected;
- setAlpha(mSelected ? mSelectedAlpha : mUnselectedAlpha);
+ if (mHighlightWhenSelected) {
+ setAlpha(mSelected ? mSelectedAlpha : mUnselectedAlpha);
+ }
+ if (mShowMoreWhenSelected && mMoreIcon != null) {
+ mMoreIcon.setVisibility(selected ? VISIBLE : GONE);
+ }
updateImage();
}
@@ -155,12 +115,173 @@
return mHasUnseen;
}
+ /**
+ * @return The app categories the component represents
+ */
+ public String[] getCategories() {
+ if (mButtonCategories == null) {
+ return new String[0];
+ }
+ return mButtonCategories;
+ }
+
+ /**
+ * @return The valid packages that should be considered.
+ */
+ public String[] getPackages() {
+ if (mButtonPackages == null) {
+ return new String[0];
+ }
+ return mButtonPackages;
+ }
+
+ /**
+ * @return The list of component names.
+ */
+ public String[] getComponentName() {
+ if (mComponentNames == null) {
+ return new String[0];
+ }
+ return mComponentNames;
+ }
+
+ /**
+ * @return The id of the display the button is on or Display.INVALID_DISPLAY if it's not yet on
+ * a display.
+ */
+ protected int getDisplayId() {
+ Display display = getDisplay();
+ if (display == null) {
+ return Display.INVALID_DISPLAY;
+ }
+ return display.getDisplayId();
+ }
+
+ protected boolean hasSelectionState() {
+ return mHighlightWhenSelected || mShowMoreWhenSelected;
+ }
+
+ /**
+ * Sets up intents for click, long touch, and broadcast.
+ */
+ protected void setUpIntents(TypedArray typedArray) {
+ mIntent = typedArray.getString(R.styleable.CarNavigationButton_intent);
+ mLongIntent = typedArray.getString(R.styleable.CarNavigationButton_longIntent);
+ mBroadcastIntent = typedArray.getBoolean(R.styleable.CarNavigationButton_broadcast, false);
+
+ String categoryString = typedArray.getString(R.styleable.CarNavigationButton_categories);
+ String packageString = typedArray.getString(R.styleable.CarNavigationButton_packages);
+ String componentNameString =
+ typedArray.getString(R.styleable.CarNavigationButton_componentNames);
+
+ try {
+ if (mIntent != null) {
+ final Intent intent = Intent.parseUri(mIntent, Intent.URI_INTENT_SCHEME);
+ setOnClickListener(getButtonClickListener(intent));
+ if (packageString != null) {
+ mButtonPackages = packageString.split(BUTTON_FILTER_DELIMITER);
+ intent.putExtra(EXTRA_BUTTON_PACKAGES, mButtonPackages);
+ }
+ if (categoryString != null) {
+ mButtonCategories = categoryString.split(BUTTON_FILTER_DELIMITER);
+ intent.putExtra(EXTRA_BUTTON_CATEGORIES, mButtonCategories);
+ }
+ if (componentNameString != null) {
+ mComponentNames = componentNameString.split(BUTTON_FILTER_DELIMITER);
+ }
+ }
+ } catch (URISyntaxException e) {
+ throw new RuntimeException("Failed to attach intent", e);
+ }
+
+ try {
+ if (mLongIntent != null && (Build.IS_ENG || Build.IS_USERDEBUG)) {
+ final Intent intent = Intent.parseUri(mLongIntent, Intent.URI_INTENT_SCHEME);
+ setOnLongClickListener(getButtonLongClickListener(intent));
+ }
+ } catch (URISyntaxException e) {
+ throw new RuntimeException("Failed to attach long press intent", e);
+ }
+ }
+
+ /** Defines the behavior of a button click. */
+ protected OnClickListener getButtonClickListener(Intent toSend) {
+ return v -> {
+ mContext.sendBroadcastAsUser(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS),
+ UserHandle.CURRENT);
+ try {
+ if (mBroadcastIntent) {
+ mContext.sendBroadcastAsUser(toSend, UserHandle.CURRENT);
+ return;
+ }
+ ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(mContext.getDisplayId());
+ mContext.startActivityAsUser(toSend, options.toBundle(),
+ UserHandle.CURRENT);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to launch intent", e);
+ }
+ };
+ }
+
+ /** Defines the behavior of a long click. */
+ protected OnLongClickListener getButtonLongClickListener(Intent toSend) {
+ return v -> {
+ mContext.sendBroadcastAsUser(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS),
+ UserHandle.CURRENT);
+ try {
+ ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(mContext.getDisplayId());
+ mContext.startActivityAsUser(toSend, options.toBundle(),
+ UserHandle.CURRENT);
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to launch intent", e);
+ }
+ // consume event either way
+ return true;
+ };
+ }
+
+
+ /**
+ * Initializes view-related aspects of the button.
+ */
+ private void setUpIcons(TypedArray typedArray) {
+ mSelectedAlpha = typedArray.getFloat(
+ R.styleable.CarNavigationButton_selectedAlpha, DEFAULT_SELECTED_ALPHA);
+ mUnselectedAlpha = typedArray.getFloat(
+ R.styleable.CarNavigationButton_unselectedAlpha, DEFAULT_UNSELECTED_ALPHA);
+ mHighlightWhenSelected = typedArray.getBoolean(
+ R.styleable.CarNavigationButton_highlightWhenSelected,
+ mHighlightWhenSelected);
+ mShowMoreWhenSelected = typedArray.getBoolean(
+ R.styleable.CarNavigationButton_showMoreWhenSelected,
+ mShowMoreWhenSelected);
+
+ mSelectedIconResourceId = typedArray.getResourceId(
+ R.styleable.CarNavigationButton_selectedIcon, mIconResourceId);
+ mIconResourceId = typedArray.getResourceId(
+ R.styleable.CarNavigationButton_icon, 0);
+
+ mIcon = findViewById(R.id.car_nav_button_icon_image);
+ mIcon.setScaleType(ImageView.ScaleType.CENTER);
+ mIcon.setClickable(false);
+ // Always apply selected alpha if the button does not toggle alpha based on selection state.
+ mIcon.setAlpha(mHighlightWhenSelected ? mUnselectedAlpha : mSelectedAlpha);
+ mIcon.setImageResource(mIconResourceId);
+
+ mMoreIcon = findViewById(R.id.car_nav_button_more_icon);
+ mMoreIcon.setClickable(false);
+ mMoreIcon.setAlpha(mSelectedAlpha);
+ mMoreIcon.setVisibility(GONE);
+ }
+
private void updateImage() {
if (mHasUnseen) {
- setImageResource(mSelected ? UNSEEN_SELECTED_ICON_RESOURCE_ID
+ mIcon.setImageResource(mSelected ? UNSEEN_SELECTED_ICON_RESOURCE_ID
: UNSEEN_ICON_RESOURCE_ID);
} else {
- setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId);
+ mIcon.setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId);
}
}
}
diff --git a/packages/CarSystemUI/tests/res/layout/car_button_selection_state_controller_test.xml b/packages/CarSystemUI/tests/res/layout/car_button_selection_state_controller_test.xml
new file mode 100644
index 0000000..f0e0216
--- /dev/null
+++ b/packages/CarSystemUI/tests/res/layout/car_button_selection_state_controller_test.xml
@@ -0,0 +1,55 @@
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:id="@id/nav_buttons"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:paddingStart="20dp"
+ android:paddingEnd="20dp"
+ android:gravity="center">
+
+ <com.android.systemui.navigationbar.car.CarNavigationButton
+ android:id="@+id/detectable_by_component_name"
+ style="@style/NavigationBarButton"
+ systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
+ systemui:icon="@drawable/car_ic_overview"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
+ systemui:highlightWhenSelected="true"
+ />
+
+ <com.android.systemui.navigationbar.car.CarNavigationButton
+ android:id="@+id/detectable_by_category"
+ style="@style/NavigationBarButton"
+ systemui:categories="android.intent.category.APP_MAPS"
+ systemui:icon="@drawable/car_ic_navigation"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.APP_MAPS;launchFlags=0x14000000;end"
+ systemui:highlightWhenSelected="true"
+ />
+
+ <com.android.systemui.navigationbar.car.CarNavigationButton
+ android:id="@+id/detectable_by_package"
+ style="@style/NavigationBarButton"
+ systemui:icon="@drawable/car_ic_phone"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;package=com.android.car.dialer;launchFlags=0x10000000;end"
+ systemui:packages="com.android.car.dialer"
+ systemui:highlightWhenSelected="true"
+ />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/CarSystemUI/tests/res/layout/car_navigation_button_test.xml b/packages/CarSystemUI/tests/res/layout/car_navigation_button_test.xml
new file mode 100644
index 0000000..576928c
--- /dev/null
+++ b/packages/CarSystemUI/tests/res/layout/car_navigation_button_test.xml
@@ -0,0 +1,115 @@
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:id="@id/nav_buttons"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:paddingStart="20dp"
+ android:paddingEnd="20dp"
+ android:gravity="center">
+
+ <com.android.systemui.navigationbar.car.CarNavigationButton
+ android:id="@+id/default_no_selection_state"
+ style="@style/NavigationBarButton"
+ systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
+ systemui:icon="@drawable/car_ic_overview"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
+ systemui:selectedIcon="@drawable/car_ic_overview_selected"
+ />
+
+ <com.android.systemui.navigationbar.car.CarNavigationButton
+ android:id="@+id/app_grid_activity"
+ style="@style/NavigationBarButton"
+ systemui:componentNames="com.android.car.carlauncher/.AppGridActivity"
+ systemui:icon="@drawable/car_ic_apps"
+ systemui:intent="intent:#Intent;component=com.android.car.carlauncher/.AppGridActivity;launchFlags=0x24000000;end"
+ systemui:selectedIcon="@drawable/car_ic_apps_selected"
+ systemui:highlightWhenSelected="true"
+ />
+
+ <com.android.systemui.navigationbar.car.CarNavigationButton
+ android:id="@+id/long_click_app_grid_activity"
+ style="@style/NavigationBarButton"
+ systemui:componentNames="com.android.car.carlauncher/.AppGridActivity"
+ systemui:icon="@drawable/car_ic_apps"
+ systemui:longIntent="intent:#Intent;component=com.android.car.carlauncher/.AppGridActivity;launchFlags=0x24000000;end"
+ systemui:selectedIcon="@drawable/car_ic_apps_selected"
+ systemui:highlightWhenSelected="true"
+ />
+
+ <com.android.systemui.navigationbar.car.CarNavigationButton
+ android:id="@+id/broadcast"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@null"
+ systemui:broadcast="true"
+ systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
+ />
+
+ <com.android.systemui.navigationbar.car.CarNavigationButton
+ android:id="@+id/selected_icon_undefined"
+ style="@style/NavigationBarButton"
+ systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
+ systemui:icon="@drawable/car_ic_overview"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
+ />
+
+ <com.android.systemui.navigationbar.car.CarNavigationButton
+ android:id="@+id/highlightable_no_more_button"
+ style="@style/NavigationBarButton"
+ systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
+ systemui:icon="@drawable/car_ic_overview"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
+ systemui:selectedIcon="@drawable/car_ic_overview_selected"
+ systemui:highlightWhenSelected="true"
+ />
+
+ <com.android.systemui.navigationbar.car.CarNavigationButton
+ android:id="@+id/not_highlightable_more_button"
+ style="@style/NavigationBarButton"
+ systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
+ systemui:icon="@drawable/car_ic_overview"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
+ systemui:selectedIcon="@drawable/car_ic_overview_selected"
+ systemui:showMoreWhenSelected="true"
+ />
+
+ <com.android.systemui.navigationbar.car.CarNavigationButton
+ android:id="@+id/highlightable_more_button"
+ style="@style/NavigationBarButton"
+ systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
+ systemui:icon="@drawable/car_ic_overview"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
+ systemui:selectedIcon="@drawable/car_ic_overview_selected"
+ systemui:highlightWhenSelected="true"
+ systemui:showMoreWhenSelected="true"
+ />
+
+ <com.android.systemui.navigationbar.car.CarNavigationButton
+ android:id="@+id/broadcast"
+ style="@style/NavigationBarButton"
+ systemui:componentNames="com.android.car.carlauncher/.CarLauncher"
+ systemui:icon="@drawable/car_ic_overview"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;launchFlags=0x14000000;end"
+ systemui:selectedIcon="@drawable/car_ic_overview_selected"
+ systemui:broadcast="true"
+ />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/ButtonSelectionStateControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/ButtonSelectionStateControllerTest.java
new file mode 100644
index 0000000..f94dd82
--- /dev/null
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/ButtonSelectionStateControllerTest.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.navigationbar.car;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.tests.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class ButtonSelectionStateControllerTest extends SysuiTestCase {
+
+ private static final String TEST_COMPONENT_NAME_PACKAGE = "com.android.car.carlauncher";
+ private static final String TEST_COMPONENT_NAME_CLASS = ".CarLauncher";
+ private static final String TEST_CATEGORY = "com.google.android.apps.maps";
+ private static final String TEST_CATEGORY_CLASS = ".APP_MAPS";
+ private static final String TEST_PACKAGE = "com.android.car.dialer";
+ private static final String TEST_PACKAGE_CLASS = ".Dialer";
+
+ // LinearLayout with CarNavigationButtons with different configurations.
+ private LinearLayout mTestView;
+ private ButtonSelectionStateController mButtonSelectionStateController;
+ private ComponentName mComponentName;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mTestView = (LinearLayout) LayoutInflater.from(mContext).inflate(
+ R.layout.car_button_selection_state_controller_test, /* root= */ null);
+ mButtonSelectionStateController = new ButtonSelectionStateController(mContext);
+ mButtonSelectionStateController.addAllButtonsWithSelectionState(mTestView);
+ }
+
+ @Test
+ public void onTaskChanged_buttonDetectableByComponentName_selectsAssociatedButton() {
+ CarNavigationButton testButton = mTestView.findViewById(R.id.detectable_by_component_name);
+ mComponentName = new ComponentName(TEST_COMPONENT_NAME_PACKAGE, TEST_COMPONENT_NAME_CLASS);
+ List<ActivityManager.StackInfo> testStack = createTestStack(mComponentName);
+ testButton.setSelected(false);
+ mButtonSelectionStateController.taskChanged(testStack, /* validDisplay= */ -1);
+
+ assertbuttonSelected(testButton);
+ }
+
+ @Test
+ public void onTaskChanged_buttonDetectableByCategory_selectsAssociatedButton() {
+ CarNavigationButton testButton = mTestView.findViewById(R.id.detectable_by_category);
+ mComponentName = new ComponentName(TEST_CATEGORY, TEST_CATEGORY_CLASS);
+ List<ActivityManager.StackInfo> testStack = createTestStack(mComponentName);
+ testButton.setSelected(false);
+ mButtonSelectionStateController.taskChanged(testStack, /* validDisplay= */ -1);
+
+ assertbuttonSelected(testButton);
+ }
+
+ @Test
+ public void onTaskChanged_buttonDetectableByPackage_selectsAssociatedButton() {
+ CarNavigationButton testButton = mTestView.findViewById(R.id.detectable_by_package);
+ mComponentName = new ComponentName(TEST_PACKAGE, TEST_PACKAGE_CLASS);
+ List<ActivityManager.StackInfo> testStack = createTestStack(mComponentName);
+ testButton.setSelected(false);
+ mButtonSelectionStateController.taskChanged(testStack, /* validDisplay= */ -1);
+
+ assertbuttonSelected(testButton);
+ }
+
+ @Test
+ public void onTaskChanged_deselectsPreviouslySelectedButton() {
+ CarNavigationButton oldButton = mTestView.findViewById(R.id.detectable_by_component_name);
+ mComponentName = new ComponentName(TEST_COMPONENT_NAME_PACKAGE, TEST_COMPONENT_NAME_CLASS);
+ List<ActivityManager.StackInfo> oldStack = createTestStack(mComponentName);
+ oldButton.setSelected(false);
+ mButtonSelectionStateController.taskChanged(oldStack, /* validDisplay= */ -1);
+
+ mComponentName = new ComponentName(TEST_PACKAGE, TEST_PACKAGE_CLASS);
+ List<ActivityManager.StackInfo> newStack = createTestStack(mComponentName);
+ mButtonSelectionStateController.taskChanged(newStack, /* validDisplay= */ -1);
+
+ assertButtonUnselected(oldButton);
+ }
+
+ // Comparing alpha is a valid way to verify button selection state because all test buttons use
+ // highlightWhenSelected = true.
+ private void assertbuttonSelected(CarNavigationButton button) {
+ assertThat(button.getAlpha()).isEqualTo(CarNavigationButton.DEFAULT_SELECTED_ALPHA);
+ }
+
+ private void assertButtonUnselected(CarNavigationButton button) {
+ assertThat(button.getAlpha()).isEqualTo(CarNavigationButton.DEFAULT_UNSELECTED_ALPHA);
+ }
+
+ private List<ActivityManager.StackInfo> createTestStack(ComponentName componentName) {
+ ActivityManager.StackInfo validStackInfo = new ActivityManager.StackInfo();
+ validStackInfo.displayId = -1; // No display is assigned to this test view
+ validStackInfo.topActivity = componentName;
+
+ List<ActivityManager.StackInfo> testStack = new ArrayList<>();
+ testStack.add(validStackInfo);
+
+ return testStack;
+ }
+}
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/CarNavigationBarControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/CarNavigationBarControllerTest.java
index 642b114..e0c13ed 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/CarNavigationBarControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/CarNavigationBarControllerTest.java
@@ -51,7 +51,7 @@
private TestableResources mTestableResources;
@Mock
- private CarFacetButtonController mCarFacetButtonController;
+ private ButtonSelectionStateController mButtonSelectionStateController;
@Mock
private HvacController mHvacController;
@@ -69,7 +69,7 @@
@Test
public void testConnectToHvac_callsConnect() {
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
mCarNavigationBar.connectToHvac();
@@ -79,7 +79,7 @@
@Test
public void testRemoveAllFromHvac_callsRemoveAll() {
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
mCarNavigationBar.removeAllFromHvac();
@@ -90,7 +90,7 @@
public void testGetBottomWindow_bottomDisabled_returnsNull() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, false);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window = mCarNavigationBar.getBottomWindow();
@@ -101,7 +101,7 @@
public void testGetBottomWindow_bottomEnabled_returnsWindow() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window = mCarNavigationBar.getBottomWindow();
@@ -112,7 +112,7 @@
public void testGetBottomWindow_bottomEnabled_calledTwice_returnsSameWindow() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window1 = mCarNavigationBar.getBottomWindow();
ViewGroup window2 = mCarNavigationBar.getBottomWindow();
@@ -124,7 +124,7 @@
public void testGetLeftWindow_leftDisabled_returnsNull() {
mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, false);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window = mCarNavigationBar.getLeftWindow();
assertThat(window).isNull();
}
@@ -133,7 +133,7 @@
public void testGetLeftWindow_leftEnabled_returnsWindow() {
mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window = mCarNavigationBar.getLeftWindow();
@@ -144,7 +144,7 @@
public void testGetLeftWindow_leftEnabled_calledTwice_returnsSameWindow() {
mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window1 = mCarNavigationBar.getLeftWindow();
ViewGroup window2 = mCarNavigationBar.getLeftWindow();
@@ -156,7 +156,7 @@
public void testGetRightWindow_rightDisabled_returnsNull() {
mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, false);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window = mCarNavigationBar.getRightWindow();
@@ -167,7 +167,7 @@
public void testGetRightWindow_rightEnabled_returnsWindow() {
mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window = mCarNavigationBar.getRightWindow();
@@ -178,7 +178,7 @@
public void testGetRightWindow_rightEnabled_calledTwice_returnsSameWindow() {
mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window1 = mCarNavigationBar.getRightWindow();
ViewGroup window2 = mCarNavigationBar.getRightWindow();
@@ -190,7 +190,7 @@
public void testSetBottomWindowVisibility_setTrue_isVisible() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window = mCarNavigationBar.getBottomWindow();
mCarNavigationBar.setBottomWindowVisibility(View.VISIBLE);
@@ -202,7 +202,7 @@
public void testSetBottomWindowVisibility_setFalse_isGone() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window = mCarNavigationBar.getBottomWindow();
mCarNavigationBar.setBottomWindowVisibility(View.GONE);
@@ -214,7 +214,7 @@
public void testSetLeftWindowVisibility_setTrue_isVisible() {
mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window = mCarNavigationBar.getLeftWindow();
mCarNavigationBar.setLeftWindowVisibility(View.VISIBLE);
@@ -226,7 +226,7 @@
public void testSetLeftWindowVisibility_setFalse_isGone() {
mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window = mCarNavigationBar.getLeftWindow();
mCarNavigationBar.setLeftWindowVisibility(View.GONE);
@@ -238,7 +238,7 @@
public void testSetRightWindowVisibility_setTrue_isVisible() {
mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window = mCarNavigationBar.getRightWindow();
mCarNavigationBar.setRightWindowVisibility(View.VISIBLE);
@@ -250,7 +250,7 @@
public void testSetRightWindowVisibility_setFalse_isGone() {
mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
ViewGroup window = mCarNavigationBar.getRightWindow();
mCarNavigationBar.setRightWindowVisibility(View.GONE);
@@ -262,7 +262,7 @@
public void testRegisterBottomBarTouchListener_createViewFirst_registrationSuccessful() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
View.OnTouchListener controller = bottomBar.getStatusBarWindowTouchListener();
@@ -277,7 +277,7 @@
public void testRegisterBottomBarTouchListener_registerFirst_registrationSuccessful() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
mCarNavigationBar.registerBottomBarTouchListener(mock(View.OnTouchListener.class));
CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
@@ -290,7 +290,7 @@
public void testRegisterNotificationController_createViewFirst_registrationSuccessful() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
CarNavigationBarController.NotificationsShadeController controller =
@@ -307,7 +307,7 @@
public void testRegisterNotificationController_registerFirst_registrationSuccessful() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
mCarNavigationBar.registerNotificationController(
mock(CarNavigationBarController.NotificationsShadeController.class));
@@ -322,7 +322,7 @@
public void testShowAllKeyguardButtons_bottomEnabled_bottomKeyguardButtonsVisible() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
View bottomKeyguardButtons = bottomBar.findViewById(R.id.lock_screen_nav_buttons);
@@ -335,7 +335,7 @@
public void testShowAllKeyguardButtons_bottomEnabled_bottomNavButtonsGone() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
View bottomButtons = bottomBar.findViewById(R.id.nav_buttons);
@@ -348,7 +348,7 @@
public void testHideAllKeyguardButtons_bottomEnabled_bottomKeyguardButtonsGone() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
View bottomKeyguardButtons = bottomBar.findViewById(R.id.lock_screen_nav_buttons);
@@ -363,7 +363,7 @@
public void testHideAllKeyguardButtons_bottomEnabled_bottomNavButtonsVisible() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
View bottomButtons = bottomBar.findViewById(R.id.nav_buttons);
@@ -378,7 +378,7 @@
public void testToggleAllNotificationsUnseenIndicator_bottomEnabled_hasUnseen_setCorrectly() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
CarNavigationButton notifications = bottomBar.findViewById(R.id.notifications);
@@ -393,7 +393,7 @@
public void testToggleAllNotificationsUnseenIndicator_bottomEnabled_noUnseen_setCorrectly() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory,
- () -> mCarFacetButtonController, () -> mHvacController);
+ mButtonSelectionStateController, () -> mHvacController);
CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true);
CarNavigationButton notifications = bottomBar.findViewById(R.id.notifications);
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/CarNavigationButtonTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/CarNavigationButtonTest.java
new file mode 100644
index 0000000..e1ee616
--- /dev/null
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/CarNavigationButtonTest.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.navigationbar.car;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.keyguard.AlphaOptimizedImageButton;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.tests.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class CarNavigationButtonTest extends SysuiTestCase {
+
+ private static final String DEFAULT_BUTTON_ACTIVITY_NAME =
+ "com.android.car.carlauncher/.CarLauncher";
+ private static final String APP_GRID_BUTTON_ACTIVITY_NAME =
+ "com.android.car.carlauncher/.AppGridActivity";
+ private static final String BROADCAST_ACTION_NAME =
+ "android.car.intent.action.TOGGLE_HVAC_CONTROLS";
+
+ private ActivityManager mActivityManager;
+ // LinearLayout with CarNavigationButtons with different configurations.
+ private LinearLayout mTestView;
+ // Does not have any selection state which is the default configuration.
+ private CarNavigationButton mDefaultButton;
+
+ @Before
+ public void setUp() {
+ mContext = spy(mContext);
+ mTestView = (LinearLayout) LayoutInflater.from(mContext).inflate(
+ R.layout.car_navigation_button_test, /* root= */ null);
+ mDefaultButton = mTestView.findViewById(R.id.default_no_selection_state);
+ mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ }
+
+ @Test
+ public void onCreate_iconIsVisible() {
+ AlphaOptimizedImageButton icon = mDefaultButton.findViewById(
+ R.id.car_nav_button_icon_image);
+
+ assertThat(icon.getDrawable()).isNotNull();
+ }
+
+ @Test
+ public void onSelected_selectedIconDefined_togglesIcon() {
+ mDefaultButton.setSelected(true);
+ Drawable selectedIconDrawable = ((AlphaOptimizedImageButton) mDefaultButton.findViewById(
+ R.id.car_nav_button_icon_image)).getDrawable();
+
+
+ mDefaultButton.setSelected(false);
+ Drawable unselectedIconDrawable = ((AlphaOptimizedImageButton) mDefaultButton.findViewById(
+ R.id.car_nav_button_icon_image)).getDrawable();
+
+ assertThat(selectedIconDrawable).isNotEqualTo(unselectedIconDrawable);
+ }
+
+ @Test
+ public void onSelected_selectedIconUndefined_displaysSameIcon() {
+ CarNavigationButton selectedIconUndefinedButton = mTestView.findViewById(
+ R.id.selected_icon_undefined);
+
+ selectedIconUndefinedButton.setSelected(true);
+ Drawable selectedIconDrawable = ((AlphaOptimizedImageButton) mDefaultButton.findViewById(
+ R.id.car_nav_button_icon_image)).getDrawable();
+
+
+ selectedIconUndefinedButton.setSelected(false);
+ Drawable unselectedIconDrawable = ((AlphaOptimizedImageButton) mDefaultButton.findViewById(
+ R.id.car_nav_button_icon_image)).getDrawable();
+
+ assertThat(selectedIconDrawable).isEqualTo(unselectedIconDrawable);
+ }
+
+ @Test
+ public void onUnselected_doesNotHighlightWhenSelected_applySelectedAlpha() {
+ mDefaultButton.setSelected(false);
+
+ assertThat(mDefaultButton.getAlpha()).isEqualTo(
+ CarNavigationButton.DEFAULT_SELECTED_ALPHA);
+ }
+
+ @Test
+ public void onSelected_doesNotHighlightWhenSelected_applySelectedAlpha() {
+ mDefaultButton.setSelected(true);
+
+ assertThat(mDefaultButton.getAlpha()).isEqualTo(
+ CarNavigationButton.DEFAULT_SELECTED_ALPHA);
+ }
+
+ @Test
+ public void onUnselected_highlightWhenSelected_applyDefaultUnselectedAlpha() {
+ CarNavigationButton highlightWhenSelectedButton = mTestView.findViewById(
+ R.id.highlightable_no_more_button);
+ highlightWhenSelectedButton.setSelected(false);
+
+ assertThat(highlightWhenSelectedButton.getAlpha()).isEqualTo(
+ CarNavigationButton.DEFAULT_UNSELECTED_ALPHA);
+ }
+
+ @Test
+ public void onSelected_highlightWhenSelected_applyDefaultSelectedAlpha() {
+ CarNavigationButton highlightWhenSelectedButton = mTestView.findViewById(
+ R.id.highlightable_no_more_button);
+ highlightWhenSelectedButton.setSelected(true);
+
+ assertThat(highlightWhenSelectedButton.getAlpha()).isEqualTo(
+ CarNavigationButton.DEFAULT_SELECTED_ALPHA);
+ }
+
+ @Test
+ public void onSelected_doesNotShowMoreWhenSelected_doesNotShowMoreIcon() {
+ mDefaultButton.setSelected(true);
+ AlphaOptimizedImageButton moreIcon = mDefaultButton.findViewById(
+ R.id.car_nav_button_more_icon);
+
+ assertThat(moreIcon.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onSelected_showMoreWhenSelected_showsMoreIcon() {
+ CarNavigationButton showMoreWhenSelected = mTestView.findViewById(
+ R.id.not_highlightable_more_button);
+ showMoreWhenSelected.setSelected(true);
+ AlphaOptimizedImageButton moreIcon = showMoreWhenSelected.findViewById(
+ R.id.car_nav_button_more_icon);
+
+ assertThat(moreIcon.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onUnselected_showMoreWhenSelected_doesNotShowMoreIcon() {
+ CarNavigationButton showMoreWhenSelected = mTestView.findViewById(
+ R.id.highlightable_no_more_button);
+ showMoreWhenSelected.setSelected(true);
+ showMoreWhenSelected.setSelected(false);
+ AlphaOptimizedImageButton moreIcon = showMoreWhenSelected.findViewById(
+ R.id.car_nav_button_more_icon);
+
+ assertThat(moreIcon.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onClick_launchesIntentActivity() {
+ mDefaultButton.performClick();
+
+ assertThat(getCurrentActivityName()).isEqualTo(DEFAULT_BUTTON_ACTIVITY_NAME);
+
+ CarNavigationButton appGridButton = mTestView.findViewById(R.id.app_grid_activity);
+ appGridButton.performClick();
+
+ assertThat(getCurrentActivityName()).isEqualTo(APP_GRID_BUTTON_ACTIVITY_NAME);
+ }
+
+ @Test
+ public void onLongClick_longIntentDefined_launchesLongIntentActivity() {
+ mDefaultButton.performClick();
+
+ assertThat(getCurrentActivityName()).isEqualTo(DEFAULT_BUTTON_ACTIVITY_NAME);
+
+ CarNavigationButton appGridButton = mTestView.findViewById(
+ R.id.long_click_app_grid_activity);
+ appGridButton.performLongClick();
+
+ assertThat(getCurrentActivityName()).isEqualTo(APP_GRID_BUTTON_ACTIVITY_NAME);
+ }
+
+ @Test
+ public void onClick_useBroadcast_broadcastsIntent() {
+ CarNavigationButton appGridButton = mTestView.findViewById(R.id.broadcast);
+ appGridButton.performClick();
+
+ verify(mContext).sendBroadcastAsUser(argThat(new ArgumentMatcher<Intent>() {
+ @Override
+ public boolean matches(Intent argument) {
+ return argument.getAction().equals(BROADCAST_ACTION_NAME);
+ }
+ }), any());
+ }
+
+ private String getCurrentActivityName() {
+ return mActivityManager.getRunningTasks(1).get(0).topActivity.flattenToShortString();
+ }
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 0e3f81b..aa36dca 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -266,9 +266,6 @@
dumpSetting(s, p,
Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS,
GlobalSettingsProto.Backup.BACKUP_AGENT_TIMEOUT_PARAMETERS);
- dumpSetting(s, p,
- Settings.Global.BACKUP_MULTI_USER_ENABLED,
- GlobalSettingsProto.Backup.BACKUP_MULTI_USER_ENABLED);
p.end(backupToken);
final long batteryToken = p.start(GlobalSettingsProto.BATTERY);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 4309c80..1e0c1d8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -387,8 +387,10 @@
case Settings.CALL_METHOD_SET_ALL_CONFIG: {
String prefix = getSettingPrefix(args);
Map<String, String> flags = getSettingFlags(args);
- setAllConfigSettings(prefix, flags);
- break;
+ Bundle result = new Bundle();
+ result.putBoolean(Settings.KEY_CONFIG_SET_RETURN,
+ setAllConfigSettings(prefix, flags));
+ return result;
}
case Settings.CALL_METHOD_RESET_CONFIG: {
@@ -2666,20 +2668,28 @@
return success;
}
+ /**
+ * Set Settings using consumed keyValues, returns true if the keyValues can be set, false
+ * otherwise.
+ */
public boolean setSettingsLocked(int type, int userId, String prefix,
Map<String, String> keyValues, String packageName) {
final int key = makeKey(type, userId);
SettingsState settingsState = peekSettingsStateLocked(key);
if (settingsState != null) {
+ if (SETTINGS_TYPE_CONFIG == type && settingsState.isNewConfigBannedLocked(prefix,
+ keyValues)) {
+ return false;
+ }
List<String> changedSettings =
settingsState.setSettingsLocked(prefix, keyValues, packageName);
if (!changedSettings.isEmpty()) {
notifyForConfigSettingsChangeLocked(key, prefix, changedSettings);
}
}
-
- return settingsState != null;
+ // keyValues aren't banned and can be set
+ return true;
}
public boolean deleteSettingLocked(int type, int userId, String name, boolean forceNotify,
@@ -2739,7 +2749,8 @@
public void resetSettingsLocked(int type, int userId, String packageName, int mode,
String tag) {
- resetSettingsLocked(type, userId, packageName, mode, tag, null);
+ resetSettingsLocked(type, userId, packageName, mode, tag, /*prefix=*/
+ null);
}
public void resetSettingsLocked(int type, int userId, String packageName, int mode,
@@ -2750,6 +2761,7 @@
return;
}
+ banConfigurationIfNecessary(type, prefix, settingsState);
switch (mode) {
case Settings.RESET_MODE_PACKAGE_DEFAULTS: {
for (String name : settingsState.getSettingNamesLocked()) {
@@ -3173,6 +3185,34 @@
return getTypeFromKey(key) == SETTINGS_TYPE_SSAID;
}
+ private boolean shouldBan(int type) {
+ if (SETTINGS_TYPE_CONFIG != type) {
+ return false;
+ }
+ final int callingUid = Binder.getCallingUid();
+ final int appId = UserHandle.getAppId(callingUid);
+
+ // Only non-shell resets should result in namespace banning
+ return appId != SHELL_UID;
+ }
+
+ private void banConfigurationIfNecessary(int type, @Nullable String prefix,
+ SettingsState settingsState) {
+ // Banning should be performed only for Settings.Config and for non-shell reset calls
+ if (!shouldBan(type)) {
+ return;
+ }
+ if (prefix != null) {
+ settingsState.banConfigurationLocked(prefix, getAllConfigFlags(prefix));
+ } else {
+ Set<String> configPrefixes = settingsState.getAllConfigPrefixesLocked();
+ for (String configPrefix : configPrefixes) {
+ settingsState.banConfigurationLocked(configPrefix,
+ getAllConfigFlags(configPrefix));
+ }
+ }
+ }
+
private File getSettingsFile(int key) {
if (isConfigSettingsKey(key)) {
final int userId = getUserIdFromKey(key);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 086b20f..5b1b530 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -65,9 +65,12 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
/**
* This class contains the state for one type of settings. It is responsible
@@ -109,6 +112,11 @@
private static final String ATTR_ID = "id";
private static final String ATTR_NAME = "name";
+ private static final String TAG_NAMESPACE_HASHES = "namespaceHashes";
+ private static final String TAG_NAMESPACE_HASH = "namespaceHash";
+ private static final String ATTR_NAMESPACE = "namespace";
+ private static final String ATTR_BANNED_HASH = "bannedHash";
+
/**
* Non-binary value will be written in this attributes.
*/
@@ -159,6 +167,9 @@
private final ArrayMap<String, Setting> mSettings = new ArrayMap<>();
@GuardedBy("mLock")
+ private final ArrayMap<String, String> mNamespaceBannedHashes = new ArrayMap<>();
+
+ @GuardedBy("mLock")
private final ArrayMap<String, Integer> mPackageToMemoryUsage;
@GuardedBy("mLock")
@@ -418,6 +429,41 @@
return true;
}
+ @GuardedBy("mLock")
+ public boolean isNewConfigBannedLocked(String prefix, Map<String, String> keyValues) {
+ // Replaces old style "null" String values with actual null's. This is done to simulate
+ // what will happen to String "null" values when they are written to Settings. This needs to
+ // be done here make sure that config hash computed during is banned check matches the
+ // one computed during banning when values are already stored.
+ keyValues = removeNullValueOldStyle(keyValues);
+ String bannedHash = mNamespaceBannedHashes.get(prefix);
+ if (bannedHash == null) {
+ return false;
+ }
+ return bannedHash.equals(hashCode(keyValues));
+ }
+
+ @GuardedBy("mLock")
+ public void banConfigurationLocked(String prefix, Map<String, String> keyValues) {
+ if (prefix == null || keyValues.isEmpty()) {
+ return;
+ }
+ // The write is intentionally not scheduled here, banned hashes should and will be written
+ // when the related setting changes are written
+ mNamespaceBannedHashes.put(prefix, hashCode(keyValues));
+ }
+
+ @GuardedBy("mLock")
+ public Set<String> getAllConfigPrefixesLocked() {
+ Set<String> prefixSet = new HashSet<>();
+ final int settingsCount = mSettings.size();
+ for (int i = 0; i < settingsCount; i++) {
+ String name = mSettings.keyAt(i);
+ prefixSet.add(name.split("/")[0] + "/");
+ }
+ return prefixSet;
+ }
+
// The settings provider must hold its lock when calling here.
// Returns the list of keys which changed (added, updated, or deleted).
@GuardedBy("mLock")
@@ -710,10 +756,12 @@
boolean wroteState = false;
final int version;
final ArrayMap<String, Setting> settings;
+ final ArrayMap<String, String> namespaceBannedHashes;
synchronized (mLock) {
version = mVersion;
settings = new ArrayMap<>(mSettings);
+ namespaceBannedHashes = new ArrayMap<>(mNamespaceBannedHashes);
mDirty = false;
mWriteScheduled = false;
}
@@ -756,8 +804,19 @@
+ setting.getValue());
}
}
-
serializer.endTag(null, TAG_SETTINGS);
+
+ serializer.startTag(null, TAG_NAMESPACE_HASHES);
+ for (int i = 0; i < namespaceBannedHashes.size(); i++) {
+ String namespace = namespaceBannedHashes.keyAt(i);
+ String bannedHash = namespaceBannedHashes.get(namespace);
+ writeSingleNamespaceHash(serializer, namespace, bannedHash);
+ if (DEBUG_PERSISTENCE) {
+ Slog.i(LOG_TAG, "[PERSISTED] namespace=" + namespace
+ + ", bannedHash=" + bannedHash);
+ }
+ }
+ serializer.endTag(null, TAG_NAMESPACE_HASHES);
serializer.endDocument();
destination.finishWrite(out);
@@ -869,6 +928,21 @@
}
}
+ private static void writeSingleNamespaceHash(XmlSerializer serializer, String namespace,
+ String bannedHashCode) throws IOException {
+ if (namespace == null || bannedHashCode == null) {
+ return;
+ }
+ serializer.startTag(null, TAG_NAMESPACE_HASH);
+ serializer.attribute(null, ATTR_NAMESPACE, namespace);
+ serializer.attribute(null, ATTR_BANNED_HASH, bannedHashCode);
+ serializer.endTag(null, TAG_NAMESPACE_HASH);
+ }
+
+ private static String hashCode(Map<String, String> keyValues) {
+ return Integer.toString(keyValues.hashCode());
+ }
+
private String getValueAttribute(XmlPullParser parser, String attr, String base64Attr) {
if (mVersion >= SETTINGS_VERSION_NEW_ENCODING) {
final String value = parser.getAttributeValue(null, attr);
@@ -939,6 +1013,8 @@
String tagName = parser.getName();
if (tagName.equals(TAG_SETTINGS)) {
parseSettingsLocked(parser);
+ } else if (tagName.equals(TAG_NAMESPACE_HASHES)) {
+ parseNamespaceHash(parser);
}
}
}
@@ -982,6 +1058,37 @@
}
}
+ @GuardedBy("mLock")
+ private void parseNamespaceHash(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ if (parser.getName().equals(TAG_NAMESPACE_HASH)) {
+ String namespace = parser.getAttributeValue(null, ATTR_NAMESPACE);
+ String bannedHashCode = parser.getAttributeValue(null, ATTR_BANNED_HASH);
+ mNamespaceBannedHashes.put(namespace, bannedHashCode);
+ }
+ }
+ }
+
+ private static Map<String, String> removeNullValueOldStyle(Map<String, String> keyValues) {
+ Iterator<Map.Entry<String, String>> it = keyValues.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, String> keyValueEntry = it.next();
+ if (NULL_VALUE_OLD_STYLE.equals(keyValueEntry.getValue())) {
+ keyValueEntry.setValue(null);
+ }
+ }
+ return keyValues;
+ }
+
private final class MyHandler extends Handler {
public static final int MSG_PERSIST_SETTINGS = 1;
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 443811f..7278225 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -571,7 +571,6 @@
Settings.Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED,
Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS,
Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS,
- Settings.Global.BACKUP_MULTI_USER_ENABLED,
Settings.Global.ISOLATED_STORAGE_LOCAL,
Settings.Global.ISOLATED_STORAGE_REMOTE,
Settings.Global.APPOP_HISTORY_PARAMETERS,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index aefdce4..347d6c2 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -230,6 +230,9 @@
<!-- Permission required for CTS test - CtsOsTestCases -->
<uses-permission android:name="android.permission.MANAGE_CRATES"/>
+ <!-- Allows setting brightness from the shell -->
+ <uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"/>
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/res/values/attrs_car.xml b/packages/SystemUI/res/values/attrs_car.xml
deleted file mode 100644
index 49b87f3..0000000
--- a/packages/SystemUI/res/values/attrs_car.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<resources>
- <attr name="icon" format="reference"/>
- <attr name="selectedIcon" format="reference"/>
- <attr name="intent" format="string"/>
- <attr name="longIntent" format="string"/>
- <attr name="selectedAlpha" format="float" />
- <attr name="unselectedAlpha" format="float" />
-
- <!-- Allow for custom attribs to be added to a facet button -->
- <declare-styleable name="CarFacetButton">
- <!-- icon to be rendered (drawable) -->
- <attr name="icon"/>
- <!-- icon to be rendered when in selected state -->
- <attr name="selectedIcon"/>
- <!-- intent to start when button is click -->
- <attr name="intent"/>
- <!-- intent to start when a long press has happened -->
- <attr name="longIntent"/>
- <!-- categories that will be added as extras to the fired intents -->
- <attr name="categories" format="string"/>
- <!-- package names that will be added as extras to the fired intents -->
- <attr name="packages" format="string" />
- <!-- componentName names that will be used for detecting selected state -->
- <attr name="componentNames" format="string" />
- <!-- Alpha value to used when in selected state. Defaults 1f -->
- <attr name="selectedAlpha" />
- <!-- Alpha value to used when in un-selected state. Defaults 0.7f -->
- <attr name="unselectedAlpha" />
- <!-- Render a "more" icon. Defaults true -->
- <attr name="useMoreIcon" format="boolean" />
-
- </declare-styleable>
-
-
- <!-- Allow for custom attribs to be added to a nav button -->
- <declare-styleable name="CarNavigationButton">
- <!-- intent to start when button is click -->
- <attr name="intent" />
- <!-- intent to start when a long press has happened -->
- <attr name="longIntent" />
- <!-- start the intent as a broad cast instead of an activity if true-->
- <attr name="broadcast" format="boolean"/>
- <!-- Alpha value to used when in selected state. Defaults 1f -->
- <attr name="selectedAlpha" />
- <!-- Alpha value to used when in un-selected state. Defaults 0.7f -->
- <attr name="unselectedAlpha" />
- <!-- icon to be rendered when in selected state -->
- <attr name="selectedIcon" />
- <!-- icon to be rendered (drawable) -->
- <attr name="icon"/>
- </declare-styleable>
-
- <!-- Custom attributes to configure hvac values -->
- <declare-styleable name="TemperatureView">
- <attr name="hvacAreaId" format="integer"/>
- <attr name="hvacPropertyId" format="integer"/>
- <attr name="hvacTempFormat" format="string"/>
- </declare-styleable>
-
- <declare-styleable name="carVolumeItems"/>
- <declare-styleable name="carVolumeItems_item">
- <!-- Align with AudioAttributes.USAGE_* -->
- <attr name="usage">
- <enum name="unknown" value="0"/>
- <enum name="media" value="1"/>
- <enum name="voice_communication" value="2"/>
- <enum name="voice_communication_signalling" value="3"/>
- <enum name="alarm" value="4"/>
- <enum name="notification" value="5"/>
- <enum name="notification_ringtone" value="6"/>
- <enum name="notification_communication_request" value="7"/>
- <enum name="notification_communication_instant" value="8"/>
- <enum name="notification_communication_delayed" value="9"/>
- <enum name="notification_event" value="10"/>
- <enum name="assistance_accessibility" value="11"/>
- <enum name="assistance_navigation_guidance" value="12"/>
- <enum name="assistance_sonification" value="13"/>
- <enum name="game" value="14"/>
- <!-- hidden, do not use -->
- <!-- enum name="virtual_source" value="15"/ -->
- <enum name="assistant" value="16"/>
- </attr>
-
- <!-- Icon resource ids to render on UI -->
- <attr name="icon" />
- </declare-styleable>
-</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index e7d1c95..718522c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -85,7 +85,8 @@
boolean visibleWhenEnabled = mContext.getResources().getBoolean(
R.bool.config_showWifiIndicatorWhenEnabled);
boolean wifiVisible = mCurrentState.enabled
- && (mCurrentState.connected || !mHasMobileData || visibleWhenEnabled);
+ && ((mCurrentState.connected && mCurrentState.inetCondition == 1)
+ || !mHasMobileData || visibleWhenEnabled);
String wifiDesc = wifiVisible ? mCurrentState.ssid : null;
boolean ssidPresent = wifiVisible && mCurrentState.ssid != null;
String contentDescription = getStringIfExists(getContentDescription());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index 3451183..32da4c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -39,7 +39,8 @@
setWifiState(true, testSsid);
setWifiLevel(0);
- verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]);
+ // Connected, but still not validated - does not show
+ verifyLastWifiIcon(false, WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]);
for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) {
setWifiLevel(testLevel);
@@ -47,7 +48,8 @@
setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]);
setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, false, true);
- verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[0][testLevel]);
+ // Icon does not show if not validated
+ verifyLastWifiIcon(false, WifiIcons.WIFI_SIGNAL_STRENGTH[0][testLevel]);
}
}
@@ -70,7 +72,7 @@
testSsid);
setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, false, true);
verifyLastQsWifiIcon(true, true, WifiIcons.QS_WIFI_SIGNAL_STRENGTH[0][testLevel],
- testSsid);
+ null);
}
}
@@ -132,7 +134,7 @@
verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]);
setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, false, true);
- verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[0][testLevel]);
+ verifyLastWifiIcon(false, WifiIcons.WIFI_SIGNAL_STRENGTH[0][testLevel]);
}
@Test
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 596f62f..0be853a 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -32,6 +32,7 @@
],
libs: [
"framework-tethering",
+ "unsupportedappusage",
],
manifest: "AndroidManifestBase.xml",
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 8f99c1c..25bad64 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -23,6 +23,7 @@
import static java.util.Arrays.copyOf;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AppOpsManager;
@@ -281,11 +282,12 @@
static final int ENFORCE_PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
| PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
- | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST;
+ | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST
+ | PhoneStateListener.LISTEN_REGISTRATION_FAILURE;
static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
- PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
- PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE;
+ PhoneStateListener.LISTEN_PRECISE_CALL_STATE
+ | PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE;
static final int READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK =
PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL
@@ -2066,6 +2068,40 @@
}
@Override
+ public void notifyRegistrationFailed(int phoneId, int subId, @NonNull CellIdentity cellIdentity,
+ @NonNull String chosenPlmn, int domain, int causeCode, int additionalCauseCode) {
+ if (!checkNotifyPermission("notifyRegistrationFailed()")) {
+ return;
+ }
+
+ // In case callers don't have fine location access, pre-construct a location-free version
+ // of the CellIdentity. This will still have the PLMN ID, which should be sufficient for
+ // most purposes.
+ final CellIdentity noLocationCi = cellIdentity.sanitizeLocationInfo();
+
+ synchronized (mRecords) {
+ if (validatePhoneId(phoneId)) {
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(
+ PhoneStateListener.LISTEN_REGISTRATION_FAILURE)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onRegistrationFailed(
+ checkFineLocationAccess(r, Build.VERSION_CODES.R)
+ ? cellIdentity : noLocationCi,
+ chosenPlmn, domain, causeCode,
+ additionalCauseCode);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+ }
+ }
+ handleRemoveListLocked();
+ }
+ }
+
+ @Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 76a8f92..27e0d52 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -32,7 +32,6 @@
import android.hardware.vibrator.IVibrator;
import android.hardware.vibrator.V1_0.EffectStrength;
import android.icu.text.DateFormat;
-import android.media.AudioAttributes;
import android.media.AudioManager;
import android.os.BatteryStats;
import android.os.Binder;
@@ -54,6 +53,7 @@
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
+import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.os.WorkSource;
@@ -107,8 +107,9 @@
private static final int SCALE_VERY_LOW_MAX_AMPLITUDE = 168; // 2/3 * 255
private static final int SCALE_LOW_MAX_AMPLITUDE = 192; // 3/4 * 255
- // If a vibration is playing for longer than 5s, it's probably not haptic feedback.
- private static final long MAX_HAPTIC_FEEDBACK_DURATION = 5000;
+ // Default vibration attributes. Used when vibration is requested without attributes
+ private static final VibrationAttributes DEFAULT_ATTRIBUTES =
+ new VibrationAttributes.Builder().build();
// If HAL supports callbacks set the timeout to ASYNC_TIMEOUT_MULTIPLIER * duration.
private static final long ASYNC_TIMEOUT_MULTIPLIER = 2;
@@ -163,7 +164,7 @@
private int mHapticFeedbackIntensity;
private int mNotificationIntensity;
private int mRingIntensity;
- private SparseArray<Pair<VibrationEffect, AudioAttributes>> mAlwaysOnEffects =
+ private SparseArray<Pair<VibrationEffect, VibrationAttributes>> mAlwaysOnEffects =
new SparseArray<>();
static native boolean vibratorExists();
@@ -207,7 +208,7 @@
// with other system events, any duration calculations should be done use startTime so as
// not to be affected by discontinuities created by RTC adjustments.
public final long startTimeDebug;
- public final AudioAttributes attrs;
+ public final VibrationAttributes attrs;
public final int uid;
public final String opPkg;
public final String reason;
@@ -220,7 +221,7 @@
public VibrationEffect originalEffect;
private Vibration(IBinder token, VibrationEffect effect,
- AudioAttributes attrs, int uid, String opPkg, String reason) {
+ VibrationAttributes attrs, int uid, String opPkg, String reason) {
this.token = token;
this.effect = effect;
this.startTime = SystemClock.elapsedRealtime();
@@ -253,28 +254,7 @@
}
public boolean isHapticFeedback() {
- if (VibratorService.this.isHapticFeedback(attrs.getUsage())) {
- return true;
- }
- if (effect instanceof VibrationEffect.Prebaked) {
- VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) effect;
- switch (prebaked.getId()) {
- case VibrationEffect.EFFECT_CLICK:
- case VibrationEffect.EFFECT_DOUBLE_CLICK:
- case VibrationEffect.EFFECT_HEAVY_CLICK:
- case VibrationEffect.EFFECT_TEXTURE_TICK:
- case VibrationEffect.EFFECT_TICK:
- case VibrationEffect.EFFECT_POP:
- case VibrationEffect.EFFECT_THUD:
- return true;
- default:
- Slog.w(TAG, "Unknown prebaked vibration effect, "
- + "assuming it isn't haptic feedback.");
- return false;
- }
- }
- final long duration = effect.getDuration();
- return duration >= 0 && duration < MAX_HAPTIC_FEEDBACK_DURATION;
+ return VibratorService.this.isHapticFeedback(attrs.getUsage());
}
public boolean isNotification() {
@@ -303,13 +283,13 @@
private final long mStartTimeDebug;
private final VibrationEffect mEffect;
private final VibrationEffect mOriginalEffect;
- private final AudioAttributes mAttrs;
+ private final VibrationAttributes mAttrs;
private final int mUid;
private final String mOpPkg;
private final String mReason;
- public VibrationInfo(long startTimeDebug, VibrationEffect effect,
- VibrationEffect originalEffect, AudioAttributes attrs, int uid,
+ VibrationInfo(long startTimeDebug, VibrationEffect effect,
+ VibrationEffect originalEffect, VibrationAttributes attrs, int uid,
String opPkg, String reason) {
mStartTimeDebug = startTimeDebug;
mEffect = effect;
@@ -528,7 +508,7 @@
}
@Override // Binder call
- public boolean setAlwaysOnEffect(int id, VibrationEffect effect, AudioAttributes attrs) {
+ public boolean setAlwaysOnEffect(int id, VibrationEffect effect, VibrationAttributes attrs) {
if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) {
throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission");
}
@@ -550,8 +530,7 @@
return false;
}
if (attrs == null) {
- attrs = new AudioAttributes.Builder()
- .setUsage(AudioAttributes.USAGE_UNKNOWN)
+ attrs = new VibrationAttributes.Builder()
.build();
}
synchronized (mLock) {
@@ -610,7 +589,7 @@
@Override // Binder call
public void vibrate(int uid, String opPkg, VibrationEffect effect,
- @Nullable AudioAttributes attrs, String reason, IBinder token) {
+ @Nullable VibrationAttributes attrs, String reason, IBinder token) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "vibrate, reason = " + reason);
try {
if (!hasPermission(android.Manifest.permission.VIBRATE)) {
@@ -626,18 +605,16 @@
}
if (attrs == null) {
- attrs = new AudioAttributes.Builder()
- .setUsage(AudioAttributes.USAGE_UNKNOWN)
- .build();
+ attrs = DEFAULT_ATTRIBUTES;
}
if (shouldBypassDnd(attrs)) {
if (!(hasPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
|| hasPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
|| hasPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING))) {
- final int flags = attrs.getAllFlags()
- & ~AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
- attrs = new AudioAttributes.Builder(attrs).replaceFlags(flags).build();
+ final int flags = attrs.getFlags()
+ & ~VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
+ attrs = new VibrationAttributes.Builder(attrs).replaceFlags(flags).build();
}
}
@@ -868,18 +845,10 @@
return true;
}
- if (vib.attrs.getUsage() == AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
- return true;
- }
-
- if (vib.attrs.getUsage() == AudioAttributes.USAGE_ALARM
- || vib.attrs.getUsage() == AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY
- || vib.attrs.getUsage()
- == AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST) {
- return true;
- }
-
- return false;
+ int usage = vib.attrs.getUsage();
+ return usage == VibrationAttributes.USAGE_RINGTONE
+ || usage == VibrationAttributes.USAGE_ALARM
+ || usage == VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
}
private int getCurrentIntensityLocked(Vibration vib) {
@@ -968,13 +937,13 @@
}
}
- private static boolean shouldBypassDnd(AudioAttributes attrs) {
- return (attrs.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0;
+ private static boolean shouldBypassDnd(VibrationAttributes attrs) {
+ return attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY);
}
private int getAppOpMode(Vibration vib) {
int mode = mAppOps.checkAudioOpNoThrow(AppOpsManager.OP_VIBRATE,
- vib.attrs.getUsage(), vib.uid, vib.opPkg);
+ vib.attrs.getAudioAttributes().getUsage(), vib.uid, vib.opPkg);
if (mode == AppOpsManager.MODE_ALLOWED) {
mode = mAppOps.startOpNoThrow(AppOpsManager.OP_VIBRATE, vib.uid, vib.opPkg);
}
@@ -1100,7 +1069,7 @@
mVibrator.getDefaultRingVibrationIntensity(), UserHandle.USER_CURRENT);
}
- private void updateAlwaysOnLocked(int id, VibrationEffect effect, AudioAttributes attrs) {
+ private void updateAlwaysOnLocked(int id, VibrationEffect effect, VibrationAttributes attrs) {
// TODO: Check DND and LowPower settings
final Vibration vib = new Vibration(null, effect, attrs, 0, null, null);
final int intensity = getCurrentIntensityLocked(vib);
@@ -1116,7 +1085,7 @@
private void updateAlwaysOnLocked() {
for (int i = 0; i < mAlwaysOnEffects.size(); i++) {
int id = mAlwaysOnEffects.keyAt(i);
- Pair<VibrationEffect, AudioAttributes> pair = mAlwaysOnEffects.valueAt(i);
+ Pair<VibrationEffect, VibrationAttributes> pair = mAlwaysOnEffects.valueAt(i);
updateAlwaysOnLocked(id, pair.first, pair.second);
}
}
@@ -1148,7 +1117,7 @@
return vibratorExists();
}
- private void doVibratorOn(long millis, int amplitude, int uid, AudioAttributes attrs) {
+ private void doVibratorOn(long millis, int amplitude, int uid, VibrationAttributes attrs) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorOn");
try {
synchronized (mInputDeviceVibrators) {
@@ -1163,7 +1132,7 @@
final int vibratorCount = mInputDeviceVibrators.size();
if (vibratorCount != 0) {
for (int i = 0; i < vibratorCount; i++) {
- mInputDeviceVibrators.get(i).vibrate(millis, attrs);
+ mInputDeviceVibrators.get(i).vibrate(millis, attrs.getAudioAttributes());
}
} else {
// Note: ordering is important here! Many haptic drivers will reset their
@@ -1272,28 +1241,19 @@
}
private static boolean isNotification(int usageHint) {
- switch (usageHint) {
- case AudioAttributes.USAGE_NOTIFICATION:
- case AudioAttributes.USAGE_NOTIFICATION_EVENT:
- case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
- case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
- case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
- return true;
- default:
- return false;
- }
+ return usageHint == VibrationAttributes.USAGE_NOTIFICATION;
}
private static boolean isRingtone(int usageHint) {
- return usageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
+ return usageHint == VibrationAttributes.USAGE_RINGTONE;
}
private static boolean isHapticFeedback(int usageHint) {
- return usageHint == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION;
+ return usageHint == VibrationAttributes.USAGE_TOUCH;
}
private static boolean isAlarm(int usageHint) {
- return usageHint == AudioAttributes.USAGE_ALARM;
+ return usageHint == VibrationAttributes.USAGE_ALARM;
}
private void noteVibratorOnLocked(int uid, long millis) {
@@ -1332,11 +1292,11 @@
private class VibrateThread extends Thread {
private final VibrationEffect.Waveform mWaveform;
private final int mUid;
- private final AudioAttributes mAttrs;
+ private final VibrationAttributes mAttrs;
private boolean mForceStop;
- VibrateThread(VibrationEffect.Waveform waveform, int uid, AudioAttributes attrs) {
+ VibrateThread(VibrationEffect.Waveform waveform, int uid, VibrationAttributes attrs) {
mWaveform = waveform;
mUid = uid;
mAttrs = attrs;
@@ -1600,7 +1560,7 @@
Slog.e(TAG, "Playing external vibration: " + vib);
}
}
- final int usage = vib.getAudioAttributes().getUsage();
+ final int usage = vib.getVibrationAttributes().getUsage();
final int defaultIntensity;
final int currentIntensity;
if (isRingtone(usage)) {
@@ -1731,7 +1691,7 @@
VibrationEffect effect =
VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE);
- AudioAttributes attrs = createAudioAttributes(commonOptions);
+ VibrationAttributes attrs = createVibrationAttributes(commonOptions);
vibrate(Binder.getCallingUid(), description, effect, attrs, "Shell Command",
mToken);
return 0;
@@ -1792,7 +1752,7 @@
amplitudesList.stream().mapToInt(Integer::intValue).toArray();
effect = VibrationEffect.createWaveform(timings, amplitudes, repeat);
}
- AudioAttributes attrs = createAudioAttributes(commonOptions);
+ VibrationAttributes attrs = createVibrationAttributes(commonOptions);
vibrate(Binder.getCallingUid(), description, effect, attrs, "Shell Command",
mToken);
return 0;
@@ -1824,7 +1784,7 @@
VibrationEffect effect =
VibrationEffect.get(id, false);
- AudioAttributes attrs = createAudioAttributes(commonOptions);
+ VibrationAttributes attrs = createVibrationAttributes(commonOptions);
vibrate(Binder.getCallingUid(), description, effect, attrs, "Shell Command",
mToken);
return 0;
@@ -1833,13 +1793,13 @@
}
}
- private AudioAttributes createAudioAttributes(CommonOptions commonOptions) {
+ private VibrationAttributes createVibrationAttributes(CommonOptions commonOptions) {
final int flags = commonOptions.force
- ? AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY
+ ? VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY
: 0;
- return new AudioAttributes.Builder()
- .setUsage(AudioAttributes.USAGE_UNKNOWN)
- .setFlags(flags)
+ return new VibrationAttributes.Builder()
+ .setUsage(VibrationAttributes.USAGE_UNKNOWN)
+ .replaceFlags(flags)
.build();
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 5bbb517..a7593c7 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -17,6 +17,11 @@
package com.android.server.appop;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
+import static android.app.AppOpsManager.FILTER_BY_FEATURE_ID;
+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;
+import static android.app.AppOpsManager.HistoricalOpsRequestFilter;
import static android.app.AppOpsManager.NoteOpEvent;
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_COARSE_LOCATION;
@@ -53,7 +58,6 @@
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.AppOpsManager.HistoricalOps;
-import android.app.AppOpsManager.HistoricalOpsRequest;
import android.app.AppOpsManager.Mode;
import android.app.AppOpsManager.OpEntry;
import android.app.AppOpsManager.OpFeatureEntry;
@@ -632,6 +636,7 @@
}
private final class FeatureOp {
+ public final @Nullable String featureId;
public final @NonNull Op parent;
/**
@@ -658,7 +663,8 @@
@GuardedBy("AppOpsService.this")
private @Nullable ArrayMap<IBinder, InProgressStartOpEvent> mInProgressEvents;
- FeatureOp(@NonNull Op parent) {
+ FeatureOp(@Nullable String featureId, @NonNull Op parent) {
+ this.featureId = featureId;
this.parent = parent;
}
@@ -676,6 +682,9 @@
@OpFlags int flags) {
accessed(System.currentTimeMillis(), -1, proxyUid, proxyPackageName,
proxyFeatureId, uidState, flags);
+
+ mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, parent.packageName,
+ featureId, uidState, flags);
}
/**
@@ -720,6 +729,9 @@
*/
public void rejected(@AppOpsManager.UidState int uidState, @OpFlags int flags) {
rejected(System.currentTimeMillis(), uidState, flags);
+
+ mHistoricalRegistry.incrementOpRejected(parent.op, parent.uid, parent.packageName,
+ featureId, uidState, flags);
}
/**
@@ -780,7 +792,7 @@
// startOp events don't support proxy, hence use flags==SELF
mHistoricalRegistry.incrementOpAccessedCount(parent.op, parent.uid, parent.packageName,
- uidState, OP_FLAG_SELF);
+ featureId, uidState, OP_FLAG_SELF);
}
/**
@@ -820,8 +832,8 @@
mAccessEvents.put(makeKey(event.getUidState(), OP_FLAG_SELF), finishedEvent);
mHistoricalRegistry.increaseOpAccessDuration(parent.op, parent.uid,
- parent.packageName, event.getUidState(), AppOpsManager.OP_FLAG_SELF,
- finishedEvent.getDuration());
+ parent.packageName, featureId, event.getUidState(),
+ AppOpsManager.OP_FLAG_SELF, finishedEvent.getDuration());
mInProgressStartOpEventPool.release(event);
@@ -1031,7 +1043,7 @@
featureOp = mFeatures.get(featureId);
if (featureOp == null) {
- featureOp = new FeatureOp(parent);
+ featureOp = new FeatureOp(featureId, parent);
mFeatures.put(featureId, featureOp);
}
@@ -1697,18 +1709,47 @@
}
}
+ /**
+ * 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) {
+ if ((filter & FILTER_BY_UID) != 0) {
+ Preconditions.checkArgument(uid != Process.INVALID_UID);
+ } else {
+ Preconditions.checkArgument(uid == Process.INVALID_UID);
+ }
+
+ if ((filter & FILTER_BY_PACKAGE_NAME) != 0) {
+ Objects.requireNonNull(packageName);
+ } else {
+ Preconditions.checkArgument(packageName == null);
+ }
+
+ if ((filter & FILTER_BY_FEATURE_ID) == 0) {
+ Preconditions.checkArgument(featureId == null);
+ }
+
+ if ((filter & FILTER_BY_OP_NAMES) != 0) {
+ Objects.requireNonNull(opNames);
+ } else {
+ Preconditions.checkArgument(opNames == null);
+ }
+
+ Preconditions.checkFlagsArgument(filter,
+ FILTER_BY_UID | FILTER_BY_PACKAGE_NAME | FILTER_BY_FEATURE_ID | FILTER_BY_OP_NAMES);
+ Preconditions.checkArgumentNonnegative(beginTimeMillis);
+ Preconditions.checkArgument(endTimeMillis > beginTimeMillis);
+ Preconditions.checkFlagsArgument(flags, OP_FLAGS_ALL);
+ }
+
@Override
- public void getHistoricalOps(int uid, @NonNull String packageName,
- @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
- @OpFlags int flags, @NonNull RemoteCallback callback) {
- // Use the builder to validate arguments.
- new HistoricalOpsRequest.Builder(
- beginTimeMillis, endTimeMillis)
- .setUid(uid)
- .setPackageName(packageName)
- .setOpNames(opNames)
- .setFlags(flags)
- .build();
+ public void getHistoricalOps(int uid, String packageName, String featureId,
+ List<String> opNames, int filter, long beginTimeMillis, long endTimeMillis,
+ int flags, RemoteCallback callback) {
+ ensureHistoricalOpRequestIsValid(uid, packageName, featureId, opNames, filter,
+ beginTimeMillis, endTimeMillis, flags);
Objects.requireNonNull(callback, "callback cannot be null");
mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
@@ -1718,22 +1759,16 @@
? opNames.toArray(new String[opNames.size()]) : null;
// Must not hold the appops lock
- mHistoricalRegistry.getHistoricalOps(uid, packageName, opNamesArray,
+ mHistoricalRegistry.getHistoricalOps(uid, packageName, featureId, opNamesArray, filter,
beginTimeMillis, endTimeMillis, flags, callback);
}
@Override
- public void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName,
- @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
- @OpFlags int flags, @NonNull RemoteCallback callback) {
- // Use the builder to validate arguments.
- new HistoricalOpsRequest.Builder(
- beginTimeMillis, endTimeMillis)
- .setUid(uid)
- .setPackageName(packageName)
- .setOpNames(opNames)
- .setFlags(flags)
- .build();
+ public void getHistoricalOpsFromDiskRaw(int uid, String packageName, String featureId,
+ List<String> opNames, int filter, long beginTimeMillis, long endTimeMillis,
+ int flags, RemoteCallback callback) {
+ ensureHistoricalOpRequestIsValid(uid, packageName, featureId, opNames, filter,
+ beginTimeMillis, endTimeMillis, flags);
Objects.requireNonNull(callback, "callback cannot be null");
mContext.enforcePermission(Manifest.permission.MANAGE_APPOPS,
@@ -1743,8 +1778,8 @@
? opNames.toArray(new String[opNames.size()]) : null;
// Must not hold the appops lock
- mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNamesArray,
- beginTimeMillis, endTimeMillis, flags, callback);
+ mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, featureId, opNamesArray,
+ filter, beginTimeMillis, endTimeMillis, flags, callback);
}
@Override
@@ -2631,8 +2666,6 @@
+ switchCode + " (" + code + ") uid " + uid + " package "
+ packageName);
featureOp.rejected(uidState.state, flags);
- mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
- uidState.state, flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName, uidMode);
return uidMode;
}
@@ -2645,8 +2678,6 @@
+ switchCode + " (" + code + ") uid " + uid + " package "
+ packageName);
featureOp.rejected(uidState.state, flags);
- mHistoricalRegistry.incrementOpRejected(code, uid, packageName,
- uidState.state, flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName, mode);
return mode;
}
@@ -2654,9 +2685,6 @@
if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
+ " package " + packageName + (featureId == null ? "" : "." + featureId));
featureOp.accessed(proxyUid, proxyPackageName, proxyFeatureId, uidState.state, flags);
- // TODO moltmann: Add features to historical app-ops
- mHistoricalRegistry.incrementOpAccessedCount(op.op, uid, packageName,
- uidState.state, flags);
scheduleOpNotedIfNeededLocked(code, uid, packageName,
AppOpsManager.MODE_ALLOWED);
@@ -2938,8 +2966,6 @@
+ switchCode + " (" + code + ") uid " + uid + " package "
+ resolvedPackageName);
featureOp.rejected(uidState.state, AppOpsManager.OP_FLAG_SELF);
- mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
- uidState.state, AppOpsManager.OP_FLAG_SELF);
return uidMode;
}
} else {
@@ -2952,8 +2978,6 @@
+ switchCode + " (" + code + ") uid " + uid + " package "
+ resolvedPackageName);
featureOp.rejected(uidState.state, AppOpsManager.OP_FLAG_SELF);
- mHistoricalRegistry.incrementOpRejected(opCode, uid, packageName,
- uidState.state, AppOpsManager.OP_FLAG_SELF);
return mode;
}
}
@@ -4437,16 +4461,24 @@
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(" --watchers");
pw.println(" Only output the watcher sections.");
pw.println(" --history");
pw.println(" Output the historical data.");
}
- private void dumpStatesLocked(@NonNull PrintWriter pw, long nowElapsed, @NonNull Op op,
- long now, @NonNull SimpleDateFormat sdf, @NonNull Date date, @NonNull String prefix) {
+ private void dumpStatesLocked(@NonNull PrintWriter pw, @Nullable String filterFeatureId,
+ @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)) {
+ continue;
+ }
+
pw.print(prefix + op.mFeatures.keyAt(i) + "=[\n");
dumpStatesLocked(pw, nowElapsed, op, op.mFeatures.keyAt(i), now, sdf, date,
prefix + " ");
@@ -4563,10 +4595,12 @@
int dumpOp = OP_NONE;
String dumpPackage = null;
+ String dumpFeatureId = null;
int dumpUid = Process.INVALID_UID;
int dumpMode = -1;
boolean dumpWatchers = false;
boolean dumpHistory = false;
+ @HistoricalOpsRequestFilter int dumpFilter = 0;
if (args != null) {
for (int i=0; i<args.length; i++) {
@@ -4583,6 +4617,7 @@
return;
}
dumpOp = Shell.strOpToOp(args[i], pw);
+ dumpFilter |= FILTER_BY_OP_NAMES;
if (dumpOp < 0) {
return;
}
@@ -4593,6 +4628,7 @@
return;
}
dumpPackage = args[i];
+ dumpFilter |= FILTER_BY_PACKAGE_NAME;
try {
dumpUid = AppGlobals.getPackageManager().getPackageUid(dumpPackage,
PackageManager.MATCH_KNOWN_PACKAGES | PackageManager.MATCH_INSTANT,
@@ -4604,6 +4640,15 @@
return;
}
dumpUid = UserHandle.getAppId(dumpUid);
+ dumpFilter |= FILTER_BY_UID;
+ } else if ("--featureId".equals(arg)) {
+ i++;
+ if (i >= args.length) {
+ pw.println("No argument for --featureId option");
+ return;
+ }
+ dumpFeatureId = args[i];
+ dumpFilter |= FILTER_BY_FEATURE_ID;
} else if ("--mode".equals(arg)) {
i++;
if (i >= args.length) {
@@ -4640,8 +4685,8 @@
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
final Date date = new Date();
boolean needSep = false;
- if (dumpOp < 0 && dumpMode < 0 && dumpPackage == null && mProfileOwners != null
- && !dumpWatchers && !dumpHistory) {
+ if (dumpFilter == 0 && dumpMode < 0 && mProfileOwners != null && !dumpWatchers
+ && !dumpHistory) {
pw.println(" Profile owners:");
for (int poi = 0; poi < mProfileOwners.size(); poi++) {
pw.print(" User #");
@@ -4944,7 +4989,8 @@
pw.print("="); pw.print(AppOpsManager.modeToName(mode));
}
pw.println("): ");
- dumpStatesLocked(pw, nowElapsed, op, now, sdf, date, " ");
+ dumpStatesLocked(pw, dumpFeatureId, dumpFilter, nowElapsed, op, now, sdf,
+ date, " ");
}
}
}
@@ -5043,7 +5089,8 @@
// Must not hold the appops lock
if (dumpHistory && !dumpWatchers) {
- mHistoricalRegistry.dump(" ", pw, dumpUid, dumpPackage, dumpOp);
+ mHistoricalRegistry.dump(" ", pw, dumpUid, dumpPackage, dumpFeatureId, dumpOp,
+ dumpFilter);
}
}
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index 2175ca0..cd450d4 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -15,12 +15,19 @@
*/
package com.android.server.appop;
+import static android.app.AppOpsManager.FILTER_BY_FEATURE_ID;
+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;
+
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;
+import android.app.AppOpsManager.HistoricalOpsRequestFilter;
import android.app.AppOpsManager.HistoricalPackageOps;
import android.app.AppOpsManager.HistoricalUidOps;
import android.app.AppOpsManager.OpFlags;
@@ -72,6 +79,7 @@
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -273,8 +281,9 @@
+ "=" + setting + " resetting!");
}
- void dump(String prefix, PrintWriter pw, int filterUid,
- String filterPackage, int filterOp) {
+ void dump(String prefix, PrintWriter pw, int filterUid, @Nullable String filterPackage,
+ @Nullable String filterFeatureId, int filterOp,
+ @HistoricalOpsRequestFilter int filter) {
if (!isApiEnabled()) {
return;
}
@@ -289,7 +298,7 @@
pw.println(AppOpsManager.historicalModeToString(mMode));
final StringDumpVisitor visitor = new StringDumpVisitor(prefix + " ",
- pw, filterUid, filterPackage, filterOp);
+ pw, filterUid, filterPackage, filterFeatureId, filterOp, filter);
final long nowMillis = System.currentTimeMillis();
// Dump in memory state first
@@ -329,7 +338,8 @@
}
void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName,
- @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis,
+ @Nullable String featureId, @Nullable String[] opNames,
+ @HistoricalOpsRequestFilter int filter, long beginTimeMillis, long endTimeMillis,
@OpFlags int flags, @NonNull RemoteCallback callback) {
if (!isApiEnabled()) {
callback.sendResult(new Bundle());
@@ -344,8 +354,8 @@
return;
}
final HistoricalOps result = new HistoricalOps(beginTimeMillis, endTimeMillis);
- mPersistence.collectHistoricalOpsDLocked(result, uid, packageName, opNames,
- beginTimeMillis, endTimeMillis, flags);
+ mPersistence.collectHistoricalOpsDLocked(result, uid, packageName, featureId,
+ opNames, filter, beginTimeMillis, endTimeMillis, flags);
final Bundle payload = new Bundle();
payload.putParcelable(AppOpsManager.KEY_HISTORICAL_OPS, result);
callback.sendResult(payload);
@@ -353,9 +363,10 @@
}
}
- void getHistoricalOps(int uid, @NonNull String packageName,
- @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis,
- @OpFlags int flags, @NonNull RemoteCallback callback) {
+ void getHistoricalOps(int uid, @NonNull String packageName, @Nullable String featureId,
+ @Nullable String[] opNames, @HistoricalOpsRequestFilter int filter,
+ long beginTimeMillis, long endTimeMillis, @OpFlags int flags,
+ @NonNull RemoteCallback callback) {
if (!isApiEnabled()) {
callback.sendResult(new Bundle());
return;
@@ -390,8 +401,8 @@
|| 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, opNames, inMemoryAdjBeginTimeMillis,
- inMemoryAdjEndTimeMillis);
+ currentOpsCopy.filter(uid, packageName, featureId, opNames, filter,
+ inMemoryAdjBeginTimeMillis, inMemoryAdjEndTimeMillis);
result.merge(currentOpsCopy);
}
pendingWrites = new ArrayList<>(mPendingWrites);
@@ -410,8 +421,8 @@
- onDiskAndInMemoryOffsetMillis, 0);
final long onDiskAdjEndTimeMillis = Math.max(inMemoryAdjEndTimeMillis
- onDiskAndInMemoryOffsetMillis, 0);
- mPersistence.collectHistoricalOpsDLocked(result, uid, packageName, opNames,
- onDiskAdjBeginTimeMillis, onDiskAdjEndTimeMillis, flags);
+ mPersistence.collectHistoricalOpsDLocked(result, uid, packageName, featureId,
+ opNames, filter, onDiskAdjBeginTimeMillis, onDiskAdjEndTimeMillis, flags);
}
// Rebase the result time to be since epoch.
@@ -425,43 +436,47 @@
}
void incrementOpAccessedCount(int op, int uid, @NonNull String packageName,
- @UidState int uidState, @OpFlags int flags) {
+ @Nullable String featureId, @UidState int uidState, @OpFlags int flags) {
synchronized (mInMemoryLock) {
if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
if (!isPersistenceInitializedMLocked()) {
Slog.e(LOG_TAG, "Interaction before persistence initialized");
return;
}
- getUpdatedPendingHistoricalOpsMLocked(System.currentTimeMillis())
- .increaseAccessCount(op, uid, packageName, uidState, flags, 1);
+ getUpdatedPendingHistoricalOpsMLocked(
+ System.currentTimeMillis()).increaseAccessCount(op, uid, packageName,
+ featureId, uidState, flags, 1);
}
}
}
void incrementOpRejected(int op, int uid, @NonNull String packageName,
- @UidState int uidState, @OpFlags int flags) {
+ @Nullable String featureId, @UidState int uidState, @OpFlags int flags) {
synchronized (mInMemoryLock) {
if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
if (!isPersistenceInitializedMLocked()) {
Slog.e(LOG_TAG, "Interaction before persistence initialized");
return;
}
- getUpdatedPendingHistoricalOpsMLocked(System.currentTimeMillis())
- .increaseRejectCount(op, uid, packageName, uidState, flags, 1);
+ getUpdatedPendingHistoricalOpsMLocked(
+ System.currentTimeMillis()).increaseRejectCount(op, uid, packageName,
+ featureId, uidState, flags, 1);
}
}
}
void increaseOpAccessDuration(int op, int uid, @NonNull String packageName,
- @UidState int uidState, @OpFlags int flags, long increment) {
+ @Nullable String featureId, @UidState int uidState, @OpFlags int flags,
+ long increment) {
synchronized (mInMemoryLock) {
if (mMode == AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE) {
if (!isPersistenceInitializedMLocked()) {
Slog.e(LOG_TAG, "Interaction before persistence initialized");
return;
}
- getUpdatedPendingHistoricalOpsMLocked(System.currentTimeMillis())
- .increaseAccessDuration(op, uid, packageName, uidState, flags, increment);
+ getUpdatedPendingHistoricalOpsMLocked(
+ System.currentTimeMillis()).increaseAccessDuration(op, uid, packageName,
+ featureId, uidState, flags, increment);
}
}
}
@@ -713,6 +728,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_OP = "op";
private static final String TAG_STATE = "st";
@@ -791,8 +807,8 @@
@Nullable List<HistoricalOps> readHistoryRawDLocked() {
return collectHistoricalOpsBaseDLocked(Process.INVALID_UID /*filterUid*/,
- null /*filterPackageName*/, null /*filterOpNames*/,
- 0 /*filterBeginTimeMills*/, Long.MAX_VALUE /*filterEndTimeMills*/,
+ null /*filterPackageName*/, null /*filterFeatureId*/, null /*filterOpNames*/,
+ 0 /*filter*/, 0 /*filterBeginTimeMills*/, Long.MAX_VALUE /*filterEndTimeMills*/,
AppOpsManager.OP_FLAGS_ALL);
}
@@ -846,11 +862,12 @@
}
private void collectHistoricalOpsDLocked(@NonNull HistoricalOps currentOps,
- int filterUid, @NonNull String filterPackageName, @Nullable String[] filterOpNames,
+ int filterUid, @Nullable String filterPackageName, @Nullable String filterFeatureId,
+ @Nullable String[] filterOpNames, @HistoricalOpsRequestFilter int filter,
long filterBeingMillis, long filterEndMillis, @OpFlags int filterFlags) {
final List<HistoricalOps> readOps = collectHistoricalOpsBaseDLocked(filterUid,
- filterPackageName, filterOpNames, filterBeingMillis, filterEndMillis,
- filterFlags);
+ filterPackageName, filterFeatureId, filterOpNames, filter, filterBeingMillis,
+ filterEndMillis, filterFlags);
if (readOps != null) {
final int readCount = readOps.size();
for (int i = 0; i < readCount; i++) {
@@ -861,7 +878,8 @@
}
private @Nullable LinkedList<HistoricalOps> collectHistoricalOpsBaseDLocked(
- int filterUid, @NonNull String filterPackageName, @Nullable String[] filterOpNames,
+ int filterUid, @Nullable String filterPackageName, @Nullable String filterFeatureId,
+ @Nullable String[] filterOpNames, @HistoricalOpsRequestFilter int filter,
long filterBeginTimeMillis, long filterEndTimeMillis, @OpFlags int filterFlags) {
File baseDir = null;
try {
@@ -874,9 +892,9 @@
final Set<String> historyFiles = getHistoricalFileNames(baseDir);
final long[] globalContentOffsetMillis = {0};
final LinkedList<HistoricalOps> ops = collectHistoricalOpsRecursiveDLocked(
- baseDir, filterUid, filterPackageName, filterOpNames, filterBeginTimeMillis,
- filterEndTimeMillis, filterFlags, globalContentOffsetMillis,
- null /*outOps*/, 0 /*depth*/, historyFiles);
+ baseDir, filterUid, filterPackageName, filterFeatureId, filterOpNames,
+ filter, filterBeginTimeMillis, filterEndTimeMillis, filterFlags,
+ globalContentOffsetMillis, null /*outOps*/, 0 /*depth*/, historyFiles);
if (DEBUG) {
filesInvariant.stopTracking(baseDir);
}
@@ -890,8 +908,9 @@
}
private @Nullable LinkedList<HistoricalOps> collectHistoricalOpsRecursiveDLocked(
- @NonNull File baseDir, int filterUid, @NonNull String filterPackageName,
- @Nullable String[] filterOpNames, long filterBeginTimeMillis,
+ @NonNull File baseDir, int filterUid, @Nullable String filterPackageName,
+ @Nullable String filterFeatureId, @Nullable String[] filterOpNames,
+ @HistoricalOpsRequestFilter int filter, long filterBeginTimeMillis,
long filterEndTimeMillis, @OpFlags int filterFlags,
@NonNull long[] globalContentOffsetMillis,
@Nullable LinkedList<HistoricalOps> outOps, int depth,
@@ -908,17 +927,17 @@
// Read historical data at this level
final List<HistoricalOps> readOps = readHistoricalOpsLocked(baseDir,
previousIntervalEndMillis, currentIntervalEndMillis, filterUid,
- filterPackageName, filterOpNames, filterBeginTimeMillis, filterEndTimeMillis,
- filterFlags, globalContentOffsetMillis, depth, historyFiles);
-
+ filterPackageName, filterFeatureId, filterOpNames, filter,
+ filterBeginTimeMillis, filterEndTimeMillis, filterFlags,
+ globalContentOffsetMillis, depth, historyFiles);
// Empty is a special signal to stop diving
if (readOps != null && readOps.isEmpty()) {
return outOps;
}
// Collect older historical data from subsequent levels
- outOps = collectHistoricalOpsRecursiveDLocked(
- baseDir, filterUid, filterPackageName, filterOpNames, filterBeginTimeMillis,
+ outOps = collectHistoricalOpsRecursiveDLocked(baseDir, filterUid, filterPackageName,
+ filterFeatureId, filterOpNames, filter, filterBeginTimeMillis,
filterEndTimeMillis, filterFlags, globalContentOffsetMillis, outOps, depth + 1,
historyFiles);
@@ -987,10 +1006,10 @@
final List<HistoricalOps> existingOps = readHistoricalOpsLocked(oldBaseDir,
previousIntervalEndMillis, currentIntervalEndMillis,
Process.INVALID_UID /*filterUid*/, null /*filterPackageName*/,
- null /*filterOpNames*/, Long.MIN_VALUE /*filterBeginTimeMillis*/,
- Long.MAX_VALUE /*filterEndTimeMillis*/, AppOpsManager.OP_FLAGS_ALL,
- null, depth, null /*historyFiles*/);
-
+ null /*filterFeatureId*/, null /*filterOpNames*/, 0 /*filter*/,
+ Long.MIN_VALUE /*filterBeginTimeMillis*/,
+ Long.MAX_VALUE /*filterEndTimeMillis*/, AppOpsManager.OP_FLAGS_ALL, null, depth,
+ null /*historyFiles*/);
if (DEBUG) {
enforceOpsWellFormed(existingOps);
}
@@ -1100,8 +1119,9 @@
}
private @Nullable List<HistoricalOps> readHistoricalOpsLocked(File baseDir,
- long intervalBeginMillis, long intervalEndMillis,
- int filterUid, @Nullable String filterPackageName, @Nullable String[] filterOpNames,
+ long intervalBeginMillis, long intervalEndMillis, int filterUid,
+ @Nullable String filterPackageName, @Nullable String filterFeatureId,
+ @Nullable String[] filterOpNames, @HistoricalOpsRequestFilter int filter,
long filterBeginTimeMillis, long filterEndTimeMillis, @OpFlags int filterFlags,
@Nullable long[] cumulativeOverflowMillis, int depth,
@NonNull Set<String> historyFiles)
@@ -1127,13 +1147,14 @@
return null;
}
}
- return readHistoricalOpsLocked(file, filterUid, filterPackageName, filterOpNames,
- filterBeginTimeMillis, filterEndTimeMillis, filterFlags,
+ return readHistoricalOpsLocked(file, filterUid, filterPackageName, filterFeatureId,
+ filterOpNames, filter, filterBeginTimeMillis, filterEndTimeMillis, filterFlags,
cumulativeOverflowMillis);
}
private @Nullable List<HistoricalOps> readHistoricalOpsLocked(@NonNull File file,
- int filterUid, @Nullable String filterPackageName, @Nullable String[] filterOpNames,
+ int filterUid, @Nullable String filterPackageName, @Nullable String filterFeatureId,
+ @Nullable String[] filterOpNames, @HistoricalOpsRequestFilter int filter,
long filterBeginTimeMillis, long filterEndTimeMillis, @OpFlags int filterFlags,
@Nullable long[] cumulativeOverflowMillis)
throws IOException, XmlPullParserException {
@@ -1158,9 +1179,10 @@
final int depth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_OPS.equals(parser.getName())) {
- final HistoricalOps ops = readeHistoricalOpsDLocked(parser,
- filterUid, filterPackageName, filterOpNames, filterBeginTimeMillis,
- filterEndTimeMillis, filterFlags, cumulativeOverflowMillis);
+ final HistoricalOps ops = readeHistoricalOpsDLocked(parser, filterUid,
+ filterPackageName, filterFeatureId, filterOpNames, filter,
+ filterBeginTimeMillis, filterEndTimeMillis, filterFlags,
+ cumulativeOverflowMillis);
if (ops == null) {
continue;
}
@@ -1193,7 +1215,8 @@
private @Nullable HistoricalOps readeHistoricalOpsDLocked(
@NonNull XmlPullParser parser, int filterUid, @Nullable String filterPackageName,
- @Nullable String[] filterOpNames, long filterBeginTimeMillis,
+ @Nullable String filterFeatureId, @Nullable String[] filterOpNames,
+ @HistoricalOpsRequestFilter int filter, long filterBeginTimeMillis,
long filterEndTimeMillis, @OpFlags int filterFlags,
@Nullable long[] cumulativeOverflowMillis)
throws IOException, XmlPullParserException {
@@ -1222,7 +1245,8 @@
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_UID.equals(parser.getName())) {
final HistoricalOps returnedOps = readHistoricalUidOpsDLocked(ops, parser,
- filterUid, filterPackageName, filterOpNames, filterFlags, filterScale);
+ filterUid, filterPackageName, filterFeatureId, filterOpNames, filter,
+ filterFlags, filterScale);
if (ops == null) {
ops = returnedOps;
}
@@ -1236,11 +1260,12 @@
private @Nullable HistoricalOps readHistoricalUidOpsDLocked(
@Nullable HistoricalOps ops, @NonNull XmlPullParser parser, int filterUid,
- @Nullable String filterPackageName, @Nullable String[] filterOpNames,
+ @Nullable String filterPackageName, @Nullable String filterFeatureId,
+ @Nullable String[] filterOpNames, @HistoricalOpsRequestFilter int filter,
@OpFlags int filterFlags, double filterScale)
throws IOException, XmlPullParserException {
final int uid = XmlUtils.readIntAttribute(parser, ATTR_NAME);
- if (filterUid != Process.INVALID_UID && filterUid != uid) {
+ if ((filter & FILTER_BY_UID) != 0 && filterUid != uid) {
XmlUtils.skipCurrentTag(parser);
return null;
}
@@ -1248,8 +1273,8 @@
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_PACKAGE.equals(parser.getName())) {
final HistoricalOps returnedOps = readHistoricalPackageOpsDLocked(ops,
- uid, parser, filterPackageName, filterOpNames, filterFlags,
- filterScale);
+ uid, parser, filterPackageName, filterFeatureId, filterOpNames, filter,
+ filterFlags, filterScale);
if (ops == null) {
ops = returnedOps;
}
@@ -1260,19 +1285,46 @@
private @Nullable HistoricalOps readHistoricalPackageOpsDLocked(
@Nullable HistoricalOps ops, int uid, @NonNull XmlPullParser parser,
- @Nullable String filterPackageName, @Nullable String[] filterOpNames,
+ @Nullable String filterPackageName, @Nullable String filterFeatureId,
+ @Nullable String[] filterOpNames, @HistoricalOpsRequestFilter int filter,
@OpFlags int filterFlags, double filterScale)
throws IOException, XmlPullParserException {
final String packageName = XmlUtils.readStringAttribute(parser, ATTR_NAME);
- if (filterPackageName != null && !filterPackageName.equals(packageName)) {
+ if ((filter & FILTER_BY_PACKAGE_NAME) != 0 && !filterPackageName.equals(packageName)) {
+ XmlUtils.skipCurrentTag(parser);
+ return null;
+ }
+ 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,
+ filterFlags, filterScale);
+ if (ops == null) {
+ ops = returnedOps;
+ }
+ }
+ }
+ 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)
+ throws IOException, XmlPullParserException {
+ final String featureId = XmlUtils.readStringAttribute(parser, ATTR_NAME);
+ if ((filter & FILTER_BY_FEATURE_ID) != 0 && !Objects.equals(filterFeatureId,
+ featureId)) {
XmlUtils.skipCurrentTag(parser);
return null;
}
final int depth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_OP.equals(parser.getName())) {
- final HistoricalOps returnedOps = readHistoricalOpDLocked(ops, uid,
- packageName, parser, filterOpNames, filterFlags, filterScale);
+ final HistoricalOps returnedOps = readHistoricalOpDLocked(ops, uid, packageName,
+ featureId, parser, filterOpNames, filter, filterFlags, filterScale);
if (ops == null) {
ops = returnedOps;
}
@@ -1282,11 +1334,13 @@
}
private @Nullable HistoricalOps readHistoricalOpDLocked(@Nullable HistoricalOps ops,
- int uid, String packageName, @NonNull XmlPullParser parser,
- @Nullable String[] filterOpNames, @OpFlags int filterFlags, double filterScale)
+ int uid, @NonNull String packageName, @Nullable String featureId,
+ @NonNull XmlPullParser parser, @Nullable String[] filterOpNames,
+ @HistoricalOpsRequestFilter int filter, @OpFlags int filterFlags,
+ double filterScale)
throws IOException, XmlPullParserException {
final int op = XmlUtils.readIntAttribute(parser, ATTR_NAME);
- if (filterOpNames != null && !ArrayUtils.contains(filterOpNames,
+ if ((filter & FILTER_BY_OP_NAMES) != 0 && !ArrayUtils.contains(filterOpNames,
AppOpsManager.opToPublicName(op))) {
XmlUtils.skipCurrentTag(parser);
return null;
@@ -1295,7 +1349,7 @@
while (XmlUtils.nextElementWithin(parser, depth)) {
if (TAG_STATE.equals(parser.getName())) {
final HistoricalOps returnedOps = readStateDLocked(ops, uid,
- packageName, op, parser, filterFlags, filterScale);
+ packageName, featureId, op, parser, filterFlags, filterScale);
if (ops == null) {
ops = returnedOps;
}
@@ -1305,8 +1359,9 @@
}
private @Nullable HistoricalOps readStateDLocked(@Nullable HistoricalOps ops,
- int uid, String packageName, int op, @NonNull XmlPullParser parser,
- @OpFlags int filterFlags, double filterScale) throws IOException {
+ int uid, @NonNull String packageName, @Nullable String featureId, int op,
+ @NonNull XmlPullParser parser, @OpFlags int filterFlags, double filterScale)
+ throws IOException {
final long key = XmlUtils.readLongAttribute(parser, ATTR_NAME);
final int flags = AppOpsManager.extractFlagsFromKey(key) & filterFlags;
if (flags == 0) {
@@ -1322,7 +1377,8 @@
if (ops == null) {
ops = new HistoricalOps(0, 0);
}
- ops.increaseAccessCount(op, uid, packageName, uidState, flags, accessCount);
+ ops.increaseAccessCount(op, uid, packageName, featureId, uidState, flags,
+ accessCount);
}
long rejectCount = XmlUtils.readLongAttribute(parser, ATTR_REJECT_COUNT, 0);
if (rejectCount > 0) {
@@ -1333,7 +1389,8 @@
if (ops == null) {
ops = new HistoricalOps(0, 0);
}
- ops.increaseRejectCount(op, uid, packageName, uidState, flags, rejectCount);
+ ops.increaseRejectCount(op, uid, packageName, featureId, uidState, flags,
+ rejectCount);
}
long accessDuration = XmlUtils.readLongAttribute(parser, ATTR_ACCESS_DURATION, 0);
if (accessDuration > 0) {
@@ -1344,7 +1401,8 @@
if (ops == null) {
ops = new HistoricalOps(0, 0);
}
- ops.increaseAccessDuration(op, uid, packageName, uidState, flags, accessDuration);
+ ops.increaseAccessDuration(op, uid, packageName, featureId, uidState, flags,
+ accessDuration);
}
return ops;
}
@@ -1409,14 +1467,26 @@
@NonNull XmlSerializer serializer) throws IOException {
serializer.startTag(null, TAG_PACKAGE);
serializer.attribute(null, ATTR_NAME, packageOps.getPackageName());
- final int opCount = packageOps.getOpCount();
- for (int i = 0; i < opCount; i++) {
- final HistoricalOp op = packageOps.getOpAt(i);
- writeHistoricalOpDLocked(op, serializer);
+ final int numFeatures = packageOps.getFeatureCount();
+ for (int i = 0; i < numFeatures; i++) {
+ final HistoricalFeatureOps op = packageOps.getFeatureOpsAt(i);
+ writeHistoricalFeatureOpsDLocked(op, serializer);
}
serializer.endTag(null, TAG_PACKAGE);
}
+ private void writeHistoricalFeatureOpsDLocked(@NonNull HistoricalFeatureOps featureOps,
+ @NonNull XmlSerializer serializer) throws IOException {
+ serializer.startTag(null, TAG_FEATURE);
+ XmlUtils.writeStringAttribute(serializer, ATTR_NAME, featureOps.getFeatureId());
+ final int opCount = featureOps.getOpCount();
+ for (int i = 0; i < opCount; i++) {
+ final HistoricalOp op = featureOps.getOpAt(i);
+ writeHistoricalOpDLocked(op, serializer);
+ }
+ serializer.endTag(null, TAG_FEATURE);
+ }
+
private void writeHistoricalOpDLocked(@NonNull HistoricalOp op,
@NonNull XmlSerializer serializer) throws IOException {
final LongSparseArray keys = op.collectKeys();
@@ -1648,24 +1718,31 @@
private final @NonNull String mOpsPrefix;
private final @NonNull String mUidPrefix;
private final @NonNull String mPackagePrefix;
+ private final @NonNull String mFeaturePrefix;
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 int mFilterOp;
+ private final @HistoricalOpsRequestFilter int mFilter;
- StringDumpVisitor(@NonNull String prefix, @NonNull PrintWriter writer,
- int filterUid, String filterPackage, int filterOp) {
+ StringDumpVisitor(@NonNull String prefix, @NonNull PrintWriter writer, int filterUid,
+ @Nullable String filterPackage, @Nullable String filterFeatureId, int filterOp,
+ @HistoricalOpsRequestFilter int filter) {
mOpsPrefix = prefix + " ";
mUidPrefix = mOpsPrefix + " ";
mPackagePrefix = mUidPrefix + " ";
- mEntryPrefix = mPackagePrefix + " ";
+ mFeaturePrefix = mPackagePrefix + " ";
+ mEntryPrefix = mFeaturePrefix + " ";
mUidStatePrefix = mEntryPrefix + " ";
mWriter = writer;
mFilterUid = filterUid;
mFilterPackage = filterPackage;
+ mFilterFeatureId = filterFeatureId;
mFilterOp = filterOp;
+ mFilter = filter;
}
@Override
@@ -1691,7 +1768,7 @@
@Override
public void visitHistoricalUidOps(HistoricalUidOps ops) {
- if (mFilterUid != Process.INVALID_UID && mFilterUid != ops.getUid()) {
+ if ((mFilter & FILTER_BY_UID) != 0 && mFilterUid != ops.getUid()) {
return;
}
mWriter.println();
@@ -1703,7 +1780,8 @@
@Override
public void visitHistoricalPackageOps(HistoricalPackageOps ops) {
- if (mFilterPackage != null && !mFilterPackage.equals(ops.getPackageName())) {
+ if ((mFilter & FILTER_BY_PACKAGE_NAME) != 0 && !mFilterPackage.equals(
+ ops.getPackageName())) {
return;
}
mWriter.print(mPackagePrefix);
@@ -1713,8 +1791,20 @@
}
@Override
+ public void visitHistoricalFeatureOps(HistoricalFeatureOps ops) {
+ if ((mFilter & FILTER_BY_FEATURE_ID) != 0 && !Objects.equals(mFilterPackage,
+ ops.getFeatureId())) {
+ return;
+ }
+ mWriter.print(mFeaturePrefix);
+ mWriter.print("Feature ");
+ mWriter.print(ops.getFeatureId());
+ mWriter.println(":");
+ }
+
+ @Override
public void visitHistoricalOp(HistoricalOp ops) {
- if (mFilterOp != AppOpsManager.OP_NONE && mFilterOp != ops.getOpCode()) {
+ if ((mFilter & FILTER_BY_OP_NAMES) != 0 && mFilterOp != ops.getOpCode()) {
return;
}
mWriter.print(mEntryPrefix);
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 10386e7..e39d6d5 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -77,7 +77,6 @@
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
-import android.provider.Settings;
import android.text.TextUtils;
import android.util.IntArray;
import android.util.Pair;
@@ -1346,6 +1345,35 @@
return SurfaceControl.getDisplayedContentSample(token, maxFrames, timestamp);
}
+ void resetBrightnessConfiguration() {
+ setBrightnessConfigurationForUserInternal(null, mContext.getUserId(),
+ mContext.getPackageName());
+ }
+
+ void setAutoBrightnessLoggingEnabled(boolean enabled) {
+ if (mDisplayPowerController != null) {
+ synchronized (mSyncRoot) {
+ mDisplayPowerController.setAutoBrightnessLoggingEnabled(enabled);
+ }
+ }
+ }
+
+ void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
+ if (mDisplayPowerController != null) {
+ synchronized (mSyncRoot) {
+ mDisplayPowerController.setDisplayWhiteBalanceLoggingEnabled(enabled);
+ }
+ }
+ }
+
+ void setAmbientColorTemperatureOverride(float cct) {
+ if (mDisplayPowerController != null) {
+ synchronized (mSyncRoot) {
+ mDisplayPowerController.setAmbientColorTemperatureOverride(cct);
+ }
+ }
+ }
+
private void onDesiredDisplayModeSpecsChangedInternal() {
boolean changed = false;
synchronized (mSyncRoot) {
@@ -2249,13 +2277,8 @@
public void onShellCommand(FileDescriptor in, FileDescriptor out,
FileDescriptor err, String[] args, ShellCallback callback,
ResultReceiver resultReceiver) {
- final long token = Binder.clearCallingIdentity();
- try {
- DisplayManagerShellCommand command = new DisplayManagerShellCommand(this);
- command.exec(this, in, out, err, args, callback, resultReceiver);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ new DisplayManagerShellCommand(DisplayManagerService.this).exec(this, in, out, err,
+ args, callback, resultReceiver);
}
@Override // Binder call
@@ -2278,40 +2301,6 @@
}
}
- void setBrightness(int brightness) {
- Settings.System.putIntForUser(mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS, brightness, UserHandle.USER_CURRENT);
- }
-
- void resetBrightnessConfiguration() {
- setBrightnessConfigurationForUserInternal(null, mContext.getUserId(),
- mContext.getPackageName());
- }
-
- void setAutoBrightnessLoggingEnabled(boolean enabled) {
- if (mDisplayPowerController != null) {
- synchronized (mSyncRoot) {
- mDisplayPowerController.setAutoBrightnessLoggingEnabled(enabled);
- }
- }
- }
-
- void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
- if (mDisplayPowerController != null) {
- synchronized (mSyncRoot) {
- mDisplayPowerController.setDisplayWhiteBalanceLoggingEnabled(enabled);
- }
- }
- }
-
- void setAmbientColorTemperatureOverride(float cct) {
- if (mDisplayPowerController != null) {
- synchronized (mSyncRoot) {
- mDisplayPowerController.setAmbientColorTemperatureOverride(cct);
- }
- }
- }
-
private boolean validatePackageName(int uid, String packageName) {
if (packageName != null) {
String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
diff --git a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
index 04d28ea..e87ad41 100644
--- a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
+++ b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
@@ -16,17 +16,22 @@
package com.android.server.display;
+import android.Manifest;
+import android.content.Context;
import android.content.Intent;
+import android.os.Binder;
import android.os.ShellCommand;
+import android.os.UserHandle;
+import android.provider.Settings;
import java.io.PrintWriter;
class DisplayManagerShellCommand extends ShellCommand {
private static final String TAG = "DisplayManagerShellCommand";
- private final DisplayManagerService.BinderService mService;
+ private final DisplayManagerService mService;
- DisplayManagerShellCommand(DisplayManagerService.BinderService service) {
+ DisplayManagerShellCommand(DisplayManagerService service) {
mService = service;
}
@@ -96,7 +101,19 @@
getErrPrintWriter().println("Error: brightness should be a number between 0 and 1");
return 1;
}
- mService.setBrightness((int) (brightness * 255));
+
+ final Context context = mService.getContext();
+ context.enforceCallingOrSelfPermission(
+ Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS,
+ "Permission required to set the display's brightness");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ Settings.System.putIntForUser(context.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS, (int) (brightness * 255),
+ UserHandle.USER_CURRENT);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
return 0;
}
diff --git a/services/core/java/com/android/server/integrity/IntegrityFileManager.java b/services/core/java/com/android/server/integrity/IntegrityFileManager.java
index 30cafaa..f90fab4 100644
--- a/services/core/java/com/android/server/integrity/IntegrityFileManager.java
+++ b/services/core/java/com/android/server/integrity/IntegrityFileManager.java
@@ -25,6 +25,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.integrity.model.RuleMetadata;
import com.android.server.integrity.parser.RuleBinaryParser;
+import com.android.server.integrity.parser.RuleIndexingController;
import com.android.server.integrity.parser.RuleMetadataParser;
import com.android.server.integrity.parser.RuleParseException;
import com.android.server.integrity.parser.RuleParser;
@@ -44,12 +45,9 @@
public class IntegrityFileManager {
private static final String TAG = "IntegrityFileManager";
- // TODO: this is a prototype implementation of this class. Thus no tests are included.
- // Implementing rule indexing will likely overhaul this class and more tests should be included
- // then.
-
private static final String METADATA_FILE = "metadata";
private static final String RULES_FILE = "rules";
+ private static final String INDEXING_FILE = "indexing";
private static final Object RULES_LOCK = new Object();
private static IntegrityFileManager sInstance = null;
@@ -64,7 +62,10 @@
// update rules atomically.
private final File mStagingDir;
- @Nullable private RuleMetadata mRuleMetadataCache;
+ @Nullable
+ private RuleMetadata mRuleMetadataCache;
+ @Nullable
+ private RuleIndexingController mRuleIndexingController;
/** Get the singleton instance of this class. */
public static synchronized IntegrityFileManager getInstance() {
@@ -103,6 +104,8 @@
Slog.e(TAG, "Error reading metadata file.", e);
}
}
+
+ updateRuleIndexingController();
}
/**
@@ -112,7 +115,8 @@
*/
public boolean initialized() {
return new File(mRulesDir, RULES_FILE).exists()
- && new File(mRulesDir, METADATA_FILE).exists();
+ && new File(mRulesDir, METADATA_FILE).exists()
+ && new File(mRulesDir, INDEXING_FILE).exists();
}
/** Write rules to persistent storage. */
@@ -125,12 +129,18 @@
// We don't consider this fatal so we continue execution.
}
- try (FileOutputStream fileOutputStream =
- new FileOutputStream(new File(mStagingDir, RULES_FILE))) {
- mRuleSerializer.serialize(rules, Optional.empty(), fileOutputStream);
+ try (FileOutputStream ruleFileOutputStream =
+ new FileOutputStream(new File(mStagingDir, RULES_FILE));
+ FileOutputStream indexingFileOutputStream =
+ new FileOutputStream(new File(mStagingDir, INDEXING_FILE))) {
+ mRuleSerializer.serialize(
+ rules, Optional.empty(), ruleFileOutputStream, indexingFileOutputStream);
}
switchStagingRulesDir();
+
+ // Update object holding the indexing information.
+ updateRuleIndexingController();
}
/**
@@ -140,10 +150,15 @@
*/
public List<Rule> readRules(AppInstallMetadata appInstallMetadata)
throws IOException, RuleParseException {
- // TODO: select rules by index
synchronized (RULES_LOCK) {
+ // Try to identify indexes from the index file.
+ List<List<Integer>> ruleReadingIndexes =
+ mRuleIndexingController.identifyRulesToEvaluate(appInstallMetadata);
+
+ // Read the rules based on the index information.
+ // TODO(b/145493956): Provide the identified indexes to the rule reader.
try (FileInputStream inputStream =
- new FileInputStream(new File(mRulesDir, RULES_FILE))) {
+ new FileInputStream(new File(mRulesDir, RULES_FILE))) {
List<Rule> rules = mRuleParser.parse(inputStream);
return rules;
}
@@ -168,6 +183,17 @@
}
}
+ private void updateRuleIndexingController() {
+ File ruleIndexingFile = new File(mRulesDir, INDEXING_FILE);
+ if (ruleIndexingFile.exists()) {
+ try (FileInputStream inputStream = new FileInputStream(ruleIndexingFile)) {
+ mRuleIndexingController = new RuleIndexingController(inputStream);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error parsing the rule indexing file.", e);
+ }
+ }
+ }
+
private void writeMetadata(File directory, String ruleProvider, String version)
throws IOException {
mRuleMetadataCache = new RuleMetadata(ruleProvider, version);
diff --git a/services/core/java/com/android/server/integrity/model/IndexingFileConstants.java b/services/core/java/com/android/server/integrity/model/IndexingFileConstants.java
new file mode 100644
index 0000000..52df89870
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/model/IndexingFileConstants.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.model;
+
+/** A helper class containing special indexing file constants. */
+public final class IndexingFileConstants {
+ // The parsing time seems acceptable for this block size based on the tests in
+ // go/ic-rule-file-format.
+ public static final int INDEXING_BLOCK_SIZE = 100;
+
+ public static final String START_INDEXING_KEY = "START_KEY";
+ public static final String END_INDEXING_KEY = "END_KEY";
+}
diff --git a/services/core/java/com/android/server/integrity/parser/BinaryFileOperations.java b/services/core/java/com/android/server/integrity/parser/BinaryFileOperations.java
new file mode 100644
index 0000000..2c5b7d3
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/parser/BinaryFileOperations.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.parser;
+
+import static com.android.server.integrity.model.ComponentBitSize.IS_HASHED_BITS;
+import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
+
+import com.android.server.integrity.IntegrityUtils;
+import com.android.server.integrity.model.BitInputStream;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * Helper methods for reading standard data structures from {@link BitInputStream}.
+ */
+public class BinaryFileOperations {
+
+ /**
+ * Read an string value with the given size and hash status from a {@code BitInputStream}.
+ *
+ * If the value is hashed, get the hex-encoding of the value. Serialized values are in raw form.
+ * All hashed values are hex-encoded.
+ */
+ public static String getStringValue(BitInputStream bitInputStream) throws IOException {
+ boolean isHashedValue = bitInputStream.getNext(IS_HASHED_BITS) == 1;
+ int valueSize = bitInputStream.getNext(VALUE_SIZE_BITS);
+ return getStringValue(bitInputStream, valueSize, isHashedValue);
+ }
+
+ /**
+ * Read an string value with the given size and hash status from a {@code BitInputStream}.
+ *
+ * If the value is hashed, get the hex-encoding of the value. Serialized values are in raw form.
+ * All hashed values are hex-encoded.
+ */
+ public static String getStringValue(
+ BitInputStream bitInputStream, int valueSize, boolean isHashedValue)
+ throws IOException {
+ if (!isHashedValue) {
+ StringBuilder value = new StringBuilder();
+ while (valueSize-- > 0) {
+ value.append((char) bitInputStream.getNext(/* numOfBits= */ 8));
+ }
+ return value.toString();
+ }
+ ByteBuffer byteBuffer = ByteBuffer.allocate(valueSize);
+ while (valueSize-- > 0) {
+ byteBuffer.put((byte) (bitInputStream.getNext(/* numOfBits= */ 8) & 0xFF));
+ }
+ return IntegrityUtils.getHexDigest(byteBuffer.array());
+ }
+
+ /** Read an integer value from a {@code BitInputStream}. */
+ public static int getIntValue(BitInputStream bitInputStream) throws IOException {
+ return bitInputStream.getNext(/* numOfBits= */ 32);
+ }
+
+ /** Read an boolean value from a {@code BitInputStream}. */
+ public static boolean getBooleanValue(BitInputStream bitInputStream) throws IOException {
+ return bitInputStream.getNext(/* numOfBits= */ 1) == 1;
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
index 8f84abc..cbb6e4e 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
@@ -28,18 +28,19 @@
import static com.android.server.integrity.model.ComponentBitSize.SEPARATOR_BITS;
import static com.android.server.integrity.model.ComponentBitSize.SIGNAL_BIT;
import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
+import static com.android.server.integrity.parser.BinaryFileOperations.getBooleanValue;
+import static com.android.server.integrity.parser.BinaryFileOperations.getIntValue;
+import static com.android.server.integrity.parser.BinaryFileOperations.getStringValue;
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
import android.content.integrity.Formula;
import android.content.integrity.Rule;
-import com.android.server.integrity.IntegrityUtils;
import com.android.server.integrity.model.BitInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
@@ -145,33 +146,4 @@
throw new IllegalArgumentException(String.format("Unknown key: %d", key));
}
}
-
- // Get value string from stream.
- // If the value is not hashed, get its raw form directly.
- // If the value is hashed, get the hex-encoding of the value. Serialized values are in raw form.
- // All hashed values are hex-encoded.
- private static String getStringValue(
- BitInputStream bitInputStream, int valueSize, boolean isHashedValue)
- throws IOException {
- if (!isHashedValue) {
- StringBuilder value = new StringBuilder();
- while (valueSize-- > 0) {
- value.append((char) bitInputStream.getNext(/* numOfBits= */ 8));
- }
- return value.toString();
- }
- ByteBuffer byteBuffer = ByteBuffer.allocate(valueSize);
- while (valueSize-- > 0) {
- byteBuffer.put((byte) (bitInputStream.getNext(/* numOfBits= */ 8) & 0xFF));
- }
- return IntegrityUtils.getHexDigest(byteBuffer.array());
- }
-
- private static int getIntValue(BitInputStream bitInputStream) throws IOException {
- return bitInputStream.getNext(/* numOfBits= */ 32);
- }
-
- private static boolean getBooleanValue(BitInputStream bitInputStream) throws IOException {
- return bitInputStream.getNext(/* numOfBits= */ 1) == 1;
- }
}
diff --git a/services/core/java/com/android/server/integrity/parser/RuleIndexingController.java b/services/core/java/com/android/server/integrity/parser/RuleIndexingController.java
new file mode 100644
index 0000000..b642fa6
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/parser/RuleIndexingController.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.parser;
+
+import static com.android.server.integrity.model.IndexingFileConstants.END_INDEXING_KEY;
+import static com.android.server.integrity.parser.BinaryFileOperations.getIntValue;
+import static com.android.server.integrity.parser.BinaryFileOperations.getStringValue;
+
+import android.content.integrity.AppInstallMetadata;
+
+import com.android.server.integrity.model.BitInputStream;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TreeMap;
+
+/** Helper class to identify the necessary indexes that needs to be read. */
+public class RuleIndexingController {
+
+ private static TreeMap<String, Integer> sPackageNameBasedIndexes;
+ private static TreeMap<String, Integer> sAppCertificateBasedIndexes;
+ private static TreeMap<String, Integer> sUnindexedRuleIndexes;
+
+ /**
+ * Provide the indexing file to read and the object will be constructed by reading and
+ * identifying the indexes.
+ */
+ public RuleIndexingController(FileInputStream fileInputStream) throws IOException {
+ BitInputStream bitInputStream = new BitInputStream(fileInputStream);
+ sPackageNameBasedIndexes = getNextIndexGroup(bitInputStream);
+ sAppCertificateBasedIndexes = getNextIndexGroup(bitInputStream);
+ sUnindexedRuleIndexes = getNextIndexGroup(bitInputStream);
+ }
+
+ /**
+ * Returns a list of integers with the starting and ending bytes of the rules that needs to be
+ * read and evaluated.
+ */
+ public List<List<Integer>> identifyRulesToEvaluate(AppInstallMetadata appInstallMetadata) {
+ // TODO(b/145493956): Identify and return the indexes that needs to be read.
+ return new ArrayList<>();
+ }
+
+ private TreeMap<String, Integer> getNextIndexGroup(BitInputStream bitInputStream)
+ throws IOException {
+ TreeMap<String, Integer> keyToIndexMap = new TreeMap<>();
+ while (bitInputStream.hasNext()) {
+ String key = getStringValue(bitInputStream);
+ int value = getIntValue(bitInputStream);
+
+ keyToIndexMap.put(key, value);
+
+ if (key == END_INDEXING_KEY) {
+ break;
+ }
+ }
+ return keyToIndexMap;
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/serializer/ByteTrackedOutputStream.java b/services/core/java/com/android/server/integrity/serializer/ByteTrackedOutputStream.java
index c8d318f..62815a9 100644
--- a/services/core/java/com/android/server/integrity/serializer/ByteTrackedOutputStream.java
+++ b/services/core/java/com/android/server/integrity/serializer/ByteTrackedOutputStream.java
@@ -27,7 +27,7 @@
*/
public class ByteTrackedOutputStream {
- private static long sWrittenBytesCount;
+ private static int sWrittenBytesCount;
private static OutputStream sOutputStream;
public ByteTrackedOutputStream(OutputStream outputStream) {
@@ -47,7 +47,7 @@
/**
* Returns the total number of bytes written into the output stream at the requested time.
*/
- public long getWrittenBytesCount() {
+ public int getWrittenBytesCount() {
return sWrittenBytesCount;
}
}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
index 22af085..b8791c3 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
@@ -27,6 +27,9 @@
import static com.android.server.integrity.model.ComponentBitSize.OPERATOR_BITS;
import static com.android.server.integrity.model.ComponentBitSize.SEPARATOR_BITS;
import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
+import static com.android.server.integrity.model.IndexingFileConstants.END_INDEXING_KEY;
+import static com.android.server.integrity.model.IndexingFileConstants.INDEXING_BLOCK_SIZE;
+import static com.android.server.integrity.model.IndexingFileConstants.START_INDEXING_KEY;
import static com.android.server.integrity.serializer.RuleIndexingDetails.APP_CERTIFICATE_INDEXED;
import static com.android.server.integrity.serializer.RuleIndexingDetails.NOT_INDEXED;
import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAGE_NAME_INDEXED;
@@ -52,20 +55,14 @@
/** A helper class to serialize rules from the {@link Rule} model to Binary representation. */
public class RuleBinarySerializer implements RuleSerializer {
- // The parsing time seems acceptable for 100 rules based on the tests in go/ic-rule-file-format.
- private static final int INDEXING_BLOCK_SIZE = 100;
-
- private static final String START_INDEXING_KEY = "START_KEY";
- private static final String END_INDEXING_KEY = "END_KEY";
-
// Get the byte representation for a list of rules.
@Override
public byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion)
throws RuleSerializeException {
try {
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- serialize(rules, formatVersion, byteArrayOutputStream);
- return byteArrayOutputStream.toByteArray();
+ ByteArrayOutputStream rulesOutputStream = new ByteArrayOutputStream();
+ serialize(rules, formatVersion, rulesOutputStream, new ByteArrayOutputStream());
+ return rulesOutputStream.toByteArray();
} catch (Exception e) {
throw new RuleSerializeException(e.getMessage(), e);
}
@@ -74,27 +71,38 @@
// Get the byte representation for a list of rules, and write them to an output stream.
@Override
public void serialize(
- List<Rule> rules, Optional<Integer> formatVersion, OutputStream originalOutputStream)
+ List<Rule> rules,
+ Optional<Integer> formatVersion,
+ OutputStream rulesFileOutputStream,
+ OutputStream indexingFileOutputStream)
throws RuleSerializeException {
try {
// Determine the indexing groups and the order of the rules within each indexed group.
Map<Integer, TreeMap<String, List<Rule>>> indexedRules =
RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets(rules);
- ByteTrackedOutputStream outputStream =
- new ByteTrackedOutputStream(originalOutputStream);
+ ByteTrackedOutputStream ruleFileByteTrackedOutputStream =
+ new ByteTrackedOutputStream(rulesFileOutputStream);
- serializeRuleFileMetadata(formatVersion, outputStream);
+ serializeRuleFileMetadata(formatVersion, ruleFileByteTrackedOutputStream);
- Map<String, Long> packageNameIndexes =
- serializeRuleList(indexedRules.get(PACKAGE_NAME_INDEXED), outputStream);
- Map<String, Long> appCertificateIndexes =
- serializeRuleList(indexedRules.get(APP_CERTIFICATE_INDEXED), outputStream);
- Map<String, Long> unindexedRulesIndex =
- serializeRuleList(indexedRules.get(NOT_INDEXED), outputStream);
+ Map<String, Integer> packageNameIndexes =
+ serializeRuleList(indexedRules.get(PACKAGE_NAME_INDEXED),
+ ruleFileByteTrackedOutputStream);
+ indexingFileOutputStream.write(
+ serializeIndexes(packageNameIndexes, /* isIndexed= */true));
- // TODO(b/145493956): Write these indexes into a index file provided by integrity file
- // manager.
+ Map<String, Integer> appCertificateIndexes =
+ serializeRuleList(indexedRules.get(APP_CERTIFICATE_INDEXED),
+ ruleFileByteTrackedOutputStream);
+ indexingFileOutputStream.write(
+ serializeIndexes(appCertificateIndexes, /* isIndexed= */true));
+
+ Map<String, Integer> unindexedRulesIndexes =
+ serializeRuleList(indexedRules.get(NOT_INDEXED),
+ ruleFileByteTrackedOutputStream);
+ indexingFileOutputStream.write(
+ serializeIndexes(unindexedRulesIndexes, /* isIndexed= */false));
} catch (Exception e) {
throw new RuleSerializeException(e.getMessage(), e);
}
@@ -109,15 +117,15 @@
outputStream.write(bitOutputStream.toByteArray());
}
- private Map<String, Long> serializeRuleList(TreeMap<String, List<Rule>> rulesMap,
+ private Map<String, Integer> serializeRuleList(TreeMap<String, List<Rule>> rulesMap,
ByteTrackedOutputStream outputStream)
throws IOException {
Preconditions.checkArgument(rulesMap != null,
"serializeRuleList should never be called with null rule list.");
BitOutputStream bitOutputStream = new BitOutputStream();
- Map<String, Long> indexMapping = new TreeMap();
- long indexTracker = 0;
+ Map<String, Integer> indexMapping = new TreeMap();
+ int indexTracker = 0;
indexMapping.put(START_INDEXING_KEY, outputStream.getWrittenBytesCount());
for (Map.Entry<String, List<Rule>> entry : rulesMap.entrySet()) {
@@ -210,6 +218,33 @@
}
}
+ private byte[] serializeIndexes(Map<String, Integer> indexes, boolean isIndexed) {
+ BitOutputStream bitOutputStream = new BitOutputStream();
+
+ // Output the starting location of this indexing group.
+ serializeStringValue(START_INDEXING_KEY, /* isHashedValue= */false,
+ bitOutputStream);
+ serializeIntValue(indexes.get(START_INDEXING_KEY), bitOutputStream);
+
+ // If the group is indexed, output the locations of the indexes.
+ if (isIndexed) {
+ for (Map.Entry<String, Integer> entry : indexes.entrySet()) {
+ if (!entry.getKey().equals(START_INDEXING_KEY)
+ && !entry.getKey().equals(END_INDEXING_KEY)) {
+ serializeStringValue(entry.getKey(), /* isHashedValue= */false,
+ bitOutputStream);
+ serializeIntValue(entry.getValue(), bitOutputStream);
+ }
+ }
+ }
+
+ // Output the end location of this indexing group.
+ serializeStringValue(END_INDEXING_KEY, /*isHashedValue= */ false, bitOutputStream);
+ serializeIntValue(indexes.get(END_INDEXING_KEY), bitOutputStream);
+
+ return bitOutputStream.toByteArray();
+ }
+
private void serializeStringValue(
String value, boolean isHashedValue, BitOutputStream bitOutputStream) {
if (value == null) {
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
index 4fcff65..2941856 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
@@ -26,10 +26,14 @@
public interface RuleSerializer {
/** Serialize rules to an output stream */
- void serialize(List<Rule> rules, Optional<Integer> formatVersion, OutputStream outputStream)
+ void serialize(
+ List<Rule> rules,
+ Optional<Integer> formatVersion,
+ OutputStream ruleFileOutputStream,
+ OutputStream indexingFileOutputStream)
throws RuleSerializeException;
/** Serialize rules to a ByteArray. */
- byte[] serialize(List<Rule> rule, Optional<Integer> formatVersion)
+ byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion)
throws RuleSerializeException;
}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
index 4c04dbc..4194432 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -56,12 +56,17 @@
@Override
public void serialize(
- List<Rule> rules, Optional<Integer> formatVersion, OutputStream outputStream)
+ List<Rule> rules,
+ Optional<Integer> formatVersion,
+ OutputStream outputStream,
+ OutputStream indexingOutputStream)
throws RuleSerializeException {
try {
XmlSerializer xmlSerializer = Xml.newSerializer();
xmlSerializer.setOutput(outputStream, StandardCharsets.UTF_8.name());
serializeRules(rules, xmlSerializer);
+
+ // TODO(b/145493956): Implement the indexing logic.
} catch (Exception e) {
throw new RuleSerializeException(e.getMessage(), e);
}
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index d2a6b42..b25e1e2 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -48,6 +48,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub {
private static final String TAG = "CrossProfileAppsService";
@@ -67,7 +68,7 @@
@Override
public List<UserHandle> getTargetUserProfiles(String callingPackage) {
- Preconditions.checkNotNull(callingPackage);
+ Objects.requireNonNull(callingPackage);
verifyCallingPackage(callingPackage);
@@ -87,8 +88,8 @@
ComponentName component,
@UserIdInt int userId,
boolean launchMainActivity) throws RemoteException {
- Preconditions.checkNotNull(callingPackage);
- Preconditions.checkNotNull(component);
+ Objects.requireNonNull(callingPackage);
+ Objects.requireNonNull(component);
verifyCallingPackage(callingPackage);
diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java
index 70c0f8d..f9cfee1 100644
--- a/services/core/java/com/android/server/pm/KeySetManagerService.java
+++ b/services/core/java/com/android/server/pm/KeySetManagerService.java
@@ -38,6 +38,7 @@
import java.io.PrintWriter;
import java.security.PublicKey;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
/*
@@ -219,10 +220,10 @@
}
public void addScannedPackageLPw(AndroidPackage pkg) {
- Preconditions.checkNotNull(pkg, "Attempted to add null pkg to ksms.");
- Preconditions.checkNotNull(pkg.getPackageName(), "Attempted to add null pkg to ksms.");
+ Objects.requireNonNull(pkg, "Attempted to add null pkg to ksms.");
+ Objects.requireNonNull(pkg.getPackageName(), "Attempted to add null pkg to ksms.");
PackageSetting ps = mPackages.get(pkg.getPackageName());
- Preconditions.checkNotNull(ps, "pkg: " + pkg.getPackageName()
+ Objects.requireNonNull(ps, "pkg: " + pkg.getPackageName()
+ "does not have a corresponding entry in mPackages.");
addSigningKeySetToPackageLPw(ps, pkg.getSigningDetails().publicKeys);
if (pkg.getKeySetMapping() != null) {
@@ -504,7 +505,7 @@
* Adds the given PublicKey to the system, deduping as it goes.
*/
private long addPublicKeyLPw(PublicKey key) {
- Preconditions.checkNotNull(key, "Cannot add null public key!");
+ Objects.requireNonNull(key, "Cannot add null public key!");
long id = getIdForPublicKeyLPr(key);
if (id != PUBLIC_KEY_NOT_FOUND) {
@@ -574,7 +575,7 @@
/* remove refs from common keysets and public keys */
PackageSetting pkg = mPackages.get(packageName);
- Preconditions.checkNotNull(pkg, "pkg name: " + packageName
+ Objects.requireNonNull(pkg, "pkg name: " + packageName
+ "does not have a corresponding entry in mPackages.");
long signingKeySetId = pkg.keySetData.getProperSigningKeySet();
decrementKeySetLPw(signingKeySetId);
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 673e265..c4ef856 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -78,6 +78,7 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
/**
* Service that manages requests and callbacks for launchers that support
@@ -136,15 +137,15 @@
public LauncherAppsImpl(Context context) {
mContext = context;
mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- mUserManagerInternal = Preconditions.checkNotNull(
+ mUserManagerInternal = Objects.requireNonNull(
LocalServices.getService(UserManagerInternal.class));
- mUsageStatsManagerInternal = Preconditions.checkNotNull(
+ mUsageStatsManagerInternal = Objects.requireNonNull(
LocalServices.getService(UsageStatsManagerInternal.class));
- mActivityManagerInternal = Preconditions.checkNotNull(
+ mActivityManagerInternal = Objects.requireNonNull(
LocalServices.getService(ActivityManagerInternal.class));
- mActivityTaskManagerInternal = Preconditions.checkNotNull(
+ mActivityTaskManagerInternal = Objects.requireNonNull(
LocalServices.getService(ActivityTaskManagerInternal.class));
- mShortcutServiceInternal = Preconditions.checkNotNull(
+ mShortcutServiceInternal = Objects.requireNonNull(
LocalServices.getService(ShortcutServiceInternal.class));
mShortcutServiceInternal.addListener(mPackageMonitor);
mCallbackHandler = BackgroundThread.getHandler();
@@ -558,7 +559,7 @@
if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
return null;
}
- Preconditions.checkNotNull(component);
+ Objects.requireNonNull(component);
// All right, create the sender.
Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT).setComponent(component);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index ac183dc..c868953 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -140,6 +140,7 @@
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@@ -511,7 +512,7 @@
this.userId = userId;
mOriginalInstallerUid = installerUid;
mInstallerUid = installerUid;
- mInstallSource = Preconditions.checkNotNull(installSource);
+ mInstallSource = Objects.requireNonNull(installSource);
this.params = params;
this.createdMillis = createdMillis;
this.updatedMillis = createdMillis;
@@ -1143,7 +1144,7 @@
* permissions.
*/
private boolean markAsCommitted(@NonNull IntentSender statusReceiver) {
- Preconditions.checkNotNull(statusReceiver);
+ Objects.requireNonNull(statusReceiver);
List<PackageInstallerSession> childSessions = getChildSessions();
@@ -1408,8 +1409,8 @@
@Override
public void transfer(String packageName, IntentSender statusReceiver) {
- Preconditions.checkNotNull(statusReceiver);
- Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(statusReceiver);
+ Objects.requireNonNull(packageName);
try {
assertCanBeTransferredAndReturnNewOwner(packageName);
@@ -1607,9 +1608,9 @@
localObserver = null;
} else {
if (!params.isMultiPackage) {
- Preconditions.checkNotNull(mPackageName);
- Preconditions.checkNotNull(mSigningDetails);
- Preconditions.checkNotNull(mResolvedBaseFile);
+ Objects.requireNonNull(mPackageName);
+ Objects.requireNonNull(mSigningDetails);
+ Objects.requireNonNull(mResolvedBaseFile);
if (needToAskForPermissionsLocked()) {
// User needs to confirm installation;
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 671450d7..0c0b93b 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -41,6 +41,7 @@
import java.io.File;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
/**
@@ -172,7 +173,7 @@
}
public void setInstallSource(InstallSource installSource) {
- this.installSource = Preconditions.checkNotNull(installSource);
+ this.installSource = Objects.requireNonNull(installSource);
}
void removeInstallerPackage(String packageName) {
diff --git a/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java b/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
index 815f885..dc534a7 100644
--- a/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
+++ b/services/core/java/com/android/server/pm/ShortcutBitmapSaver.java
@@ -38,6 +38,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Deque;
+import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingDeque;
@@ -157,7 +158,7 @@
public void saveBitmapLocked(ShortcutInfo shortcut,
int maxDimension, CompressFormat format, int quality) {
final Icon icon = shortcut.getIcon();
- Preconditions.checkNotNull(icon);
+ Objects.requireNonNull(icon);
final Bitmap original = icon.getBitmap();
if (original == null) {
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 06c71ba..0274aee 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -55,6 +55,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
@@ -454,7 +455,7 @@
public void updateInvisibleShortcutForPinRequestWith(@NonNull ShortcutInfo shortcut) {
final ShortcutInfo source = mShortcuts.get(shortcut.getId());
- Preconditions.checkNotNull(source);
+ Objects.requireNonNull(source);
mShortcutUser.mService.validateShortcutForPinRequest(shortcut);
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index 0629d9e..6d9d69e 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -28,6 +28,7 @@
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
+import java.util.Objects;
/**
* All methods should be guarded by {@code #mShortcutUser.mService.mLock}.
@@ -49,7 +50,7 @@
mShortcutUser = shortcutUser;
mPackageUserId = packageUserId;
mPackageName = Preconditions.checkStringNotEmpty(packageName);
- mPackageInfo = Preconditions.checkNotNull(packageInfo);
+ mPackageInfo = Objects.requireNonNull(packageInfo);
}
/**
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index f0a1c70..261418c 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -429,17 +429,17 @@
@VisibleForTesting
ShortcutService(Context context, Looper looper, boolean onlyForPackageManagerApis) {
- mContext = Preconditions.checkNotNull(context);
+ mContext = Objects.requireNonNull(context);
LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
mHandler = new Handler(looper);
mIPackageManager = AppGlobals.getPackageManager();
- mPackageManagerInternal = Preconditions.checkNotNull(
+ mPackageManagerInternal = Objects.requireNonNull(
LocalServices.getService(PackageManagerInternal.class));
- mUserManagerInternal = Preconditions.checkNotNull(
+ mUserManagerInternal = Objects.requireNonNull(
LocalServices.getService(UserManagerInternal.class));
- mUsageStatsManagerInternal = Preconditions.checkNotNull(
+ mUsageStatsManagerInternal = Objects.requireNonNull(
LocalServices.getService(UsageStatsManagerInternal.class));
- mActivityManagerInternal = Preconditions.checkNotNull(
+ mActivityManagerInternal = Objects.requireNonNull(
LocalServices.getService(ActivityManagerInternal.class));
mShortcutRequestPinProcessor = new ShortcutRequestPinProcessor(this, mLock);
@@ -1680,7 +1680,7 @@
"Re-publishing ShortcutInfo returned by server is not supported."
+ " Some information such as icon may lost from shortcut.");
}
- Preconditions.checkNotNull(shortcut, "Null shortcut detected");
+ Objects.requireNonNull(shortcut, "Null shortcut detected");
if (shortcut.getActivity() != null) {
Preconditions.checkState(
shortcut.getPackage().equals(shortcut.getActivity().getPackageName()),
@@ -1947,7 +1947,7 @@
@Override
public boolean requestPinShortcut(String packageName, ShortcutInfo shortcut,
IntentSender resultIntent, int userId) {
- Preconditions.checkNotNull(shortcut);
+ Objects.requireNonNull(shortcut);
Preconditions.checkArgument(shortcut.isEnabled(), "Shortcut must be enabled");
return requestPinItem(packageName, userId, shortcut, null, null, resultIntent);
}
@@ -1955,7 +1955,7 @@
@Override
public Intent createShortcutResultIntent(String packageName, ShortcutInfo shortcut, int userId)
throws RemoteException {
- Preconditions.checkNotNull(shortcut);
+ Objects.requireNonNull(shortcut);
Preconditions.checkArgument(shortcut.isEnabled(), "Shortcut must be enabled");
verifyCaller(packageName, userId);
verifyShortcutInfoPackage(packageName, shortcut);
@@ -2019,7 +2019,7 @@
public void disableShortcuts(String packageName, List shortcutIds,
CharSequence disabledMessage, int disabledMessageResId, @UserIdInt int userId) {
verifyCaller(packageName, userId);
- Preconditions.checkNotNull(shortcutIds, "shortcutIds must be provided");
+ Objects.requireNonNull(shortcutIds, "shortcutIds must be provided");
synchronized (mLock) {
throwIfUserLockedL(userId);
@@ -2054,7 +2054,7 @@
@Override
public void enableShortcuts(String packageName, List shortcutIds, @UserIdInt int userId) {
verifyCaller(packageName, userId);
- Preconditions.checkNotNull(shortcutIds, "shortcutIds must be provided");
+ Objects.requireNonNull(shortcutIds, "shortcutIds must be provided");
synchronized (mLock) {
throwIfUserLockedL(userId);
@@ -2081,7 +2081,7 @@
public void removeDynamicShortcuts(String packageName, List shortcutIds,
@UserIdInt int userId) {
verifyCaller(packageName, userId);
- Preconditions.checkNotNull(shortcutIds, "shortcutIds must be provided");
+ Objects.requireNonNull(shortcutIds, "shortcutIds must be provided");
synchronized (mLock) {
throwIfUserLockedL(userId);
@@ -2256,7 +2256,7 @@
public void reportShortcutUsed(String packageName, String shortcutId, int userId) {
verifyCaller(packageName, userId);
- Preconditions.checkNotNull(shortcutId);
+ Objects.requireNonNull(shortcutId);
if (DEBUG) {
Slog.d(TAG, String.format("reportShortcutUsed: Shortcut %s package %s used on user %d",
@@ -2713,7 +2713,7 @@
@NonNull List<String> shortcutIds, int userId) {
// Calling permission must be checked by LauncherAppsImpl.
Preconditions.checkStringNotEmpty(packageName, "packageName");
- Preconditions.checkNotNull(shortcutIds, "shortcutIds");
+ Objects.requireNonNull(shortcutIds, "shortcutIds");
synchronized (mLock) {
throwIfUserLockedL(userId);
@@ -2766,16 +2766,16 @@
@Override
public void addListener(@NonNull ShortcutChangeListener listener) {
synchronized (mLock) {
- mListeners.add(Preconditions.checkNotNull(listener));
+ mListeners.add(Objects.requireNonNull(listener));
}
}
@Override
public int getShortcutIconResId(int launcherUserId, @NonNull String callingPackage,
@NonNull String packageName, @NonNull String shortcutId, int userId) {
- Preconditions.checkNotNull(callingPackage, "callingPackage");
- Preconditions.checkNotNull(packageName, "packageName");
- Preconditions.checkNotNull(shortcutId, "shortcutId");
+ Objects.requireNonNull(callingPackage, "callingPackage");
+ Objects.requireNonNull(packageName, "packageName");
+ Objects.requireNonNull(shortcutId, "shortcutId");
synchronized (mLock) {
throwIfUserLockedL(userId);
@@ -2800,9 +2800,9 @@
public ParcelFileDescriptor getShortcutIconFd(int launcherUserId,
@NonNull String callingPackage, @NonNull String packageName,
@NonNull String shortcutId, int userId) {
- Preconditions.checkNotNull(callingPackage, "callingPackage");
- Preconditions.checkNotNull(packageName, "packageName");
- Preconditions.checkNotNull(shortcutId, "shortcutId");
+ Objects.requireNonNull(callingPackage, "callingPackage");
+ Objects.requireNonNull(packageName, "packageName");
+ Objects.requireNonNull(shortcutId, "shortcutId");
synchronized (mLock) {
throwIfUserLockedL(userId);
@@ -2854,7 +2854,7 @@
public boolean requestPinAppWidget(@NonNull String callingPackage,
@NonNull AppWidgetProviderInfo appWidget, @Nullable Bundle extras,
@Nullable IntentSender resultIntent, int userId) {
- Preconditions.checkNotNull(appWidget);
+ Objects.requireNonNull(appWidget);
return requestPinItem(callingPackage, userId, null, appWidget, extras, resultIntent);
}
@@ -2865,7 +2865,7 @@
@Override
public boolean isForegroundDefaultLauncher(@NonNull String callingPackage, int callingUid) {
- Preconditions.checkNotNull(callingPackage);
+ Objects.requireNonNull(callingPackage);
final int userId = UserHandle.getUserId(callingUid);
final ComponentName defaultLauncher = getDefaultLauncher(userId);
@@ -3411,7 +3411,7 @@
List<ResolveInfo> queryActivities(@NonNull Intent baseIntent,
@NonNull String packageName, @Nullable ComponentName activity, int userId) {
- baseIntent.setPackage(Preconditions.checkNotNull(packageName));
+ baseIntent.setPackage(Objects.requireNonNull(packageName));
if (activity != null) {
baseIntent.setComponent(activity);
}
@@ -3529,7 +3529,7 @@
@Nullable
ComponentName injectGetPinConfirmationActivity(@NonNull String launcherPackageName,
int launcherUserId, int requestType) {
- Preconditions.checkNotNull(launcherPackageName);
+ Objects.requireNonNull(launcherPackageName);
String action = requestType == LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT ?
LauncherApps.ACTION_CONFIRM_PIN_SHORTCUT :
LauncherApps.ACTION_CONFIRM_PIN_APPWIDGET;
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index 8c207a8..eab3f4d 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -75,7 +75,7 @@
private PackageWithUser(int userId, String packageName) {
this.userId = userId;
- this.packageName = Preconditions.checkNotNull(packageName);
+ this.packageName = Objects.requireNonNull(packageName);
}
public static PackageWithUser of(int userId, String packageName) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 5854e32..1455d4a 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -434,7 +434,7 @@
private final IntentSender mTarget;
public DisableQuietModeUserUnlockedCallback(IntentSender target) {
- Preconditions.checkNotNull(target);
+ Objects.requireNonNull(target);
mTarget = target;
}
@@ -884,7 +884,7 @@
@Override
public boolean requestQuietModeEnabled(@NonNull String callingPackage, boolean enableQuietMode,
@UserIdInt int userId, @Nullable IntentSender target) {
- Preconditions.checkNotNull(callingPackage);
+ Objects.requireNonNull(callingPackage);
if (enableQuietMode && target != null) {
throw new IllegalArgumentException(
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 90bd947..815f7b4 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -51,6 +51,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
/**
@@ -357,7 +358,7 @@
}
public static void merge(@NonNull Bundle dest, @Nullable Bundle in) {
- Preconditions.checkNotNull(dest);
+ Objects.requireNonNull(dest);
Preconditions.checkArgument(dest != in);
if (in == null) {
return;
@@ -661,7 +662,7 @@
public static boolean isSettingRestrictedForUser(Context context, @NonNull String setting,
int userId, String value, int callingUid) {
- Preconditions.checkNotNull(setting);
+ Objects.requireNonNull(setting);
final UserManager mUserManager = context.getSystemService(UserManager.class);
String restriction;
boolean checkAllUser = false;
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 486cfef..0caab6d 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -62,6 +62,7 @@
import java.io.File;
import java.io.FileNotFoundException;
+import java.util.Objects;
/**
* A system service that provides access to runtime and compiler artifacts.
@@ -180,7 +181,7 @@
}
// Sanity checks on the arguments.
- Preconditions.checkNotNull(callback);
+ Objects.requireNonNull(callback);
boolean bootImageProfile = profileType == ArtManager.PROFILE_BOOT_IMAGE;
if (!bootImageProfile) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 9cd6f16..d921f31 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -796,7 +796,7 @@
@Override
public int checkPermission(String permName, String pkgName, int userId) {
- // Not using Preconditions.checkNotNull() here for compatibility reasons.
+ // Not using Objects.requireNonNull() here for compatibility reasons.
if (permName == null || pkgName == null) {
return PackageManager.PERMISSION_DENIED;
}
@@ -872,7 +872,7 @@
@Override
public int checkUidPermission(String permName, int uid) {
- // Not using Preconditions.checkNotNull() here for compatibility reasons.
+ // Not using Objects.requireNonNull() here for compatibility reasons.
if (permName == null) {
return PackageManager.PERMISSION_DENIED;
}
@@ -955,7 +955,7 @@
@Override
@Nullable public List<String> getWhitelistedRestrictedPermissions(@NonNull String packageName,
@PermissionWhitelistFlags int flags, @UserIdInt int userId) {
- Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(packageName);
Preconditions.checkFlagsArgument(flags,
PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
| PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
@@ -1043,7 +1043,7 @@
@NonNull String permName, @PermissionWhitelistFlags int flags,
@UserIdInt int userId) {
// Other argument checks are done in get/setWhitelistedRestrictedPermissions
- Preconditions.checkNotNull(permName);
+ Objects.requireNonNull(permName);
if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permName)) {
return false;
@@ -1086,7 +1086,7 @@
@NonNull String permName, @PermissionWhitelistFlags int flags,
@UserIdInt int userId) {
// Other argument checks are done in get/setWhitelistedRestrictedPermissions
- Preconditions.checkNotNull(permName);
+ Objects.requireNonNull(permName);
if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permName)) {
return false;
@@ -1104,7 +1104,7 @@
private boolean setWhitelistedRestrictedPermissionsInternal(@NonNull String packageName,
@Nullable List<String> permissions, @PermissionWhitelistFlags int flags,
@UserIdInt int userId) {
- Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(packageName);
Preconditions.checkFlagsArgument(flags,
PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
| PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
@@ -3028,7 +3028,7 @@
mContext.enforceCallingPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
"Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS
+ " to register permissions as one time.");
- packageName = Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(packageName);
long token = Binder.clearCallingIdentity();
try {
@@ -3044,7 +3044,7 @@
mContext.enforceCallingPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
"Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS
+ " to remove permissions as one time.");
- Preconditions.checkNotNull(packageName);
+ Objects.requireNonNull(packageName);
long token = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 858180b..5a124a7 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -697,16 +697,7 @@
accessibilityShortcutActivated();
break;
case MSG_BUGREPORT_TV:
- boolean customBugreport = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_customBugreport);
- if (customBugreport) {
- Log.i(TAG, "Triggering a custom bugreport!");
- Intent intent = new Intent(ACTION_CUSTOM_BUGREPORT_REQUESTED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- } else {
- requestFullBugreport();
- }
+ requestFullBugreport();
break;
case MSG_ACCESSIBILITY_TV:
if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(false)) {
diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
index b0f22e4..f3a6018 100644
--- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
+++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
@@ -145,7 +145,8 @@
}
@Override
public boolean mayAllowExtraAppOp() {
- return !shouldApplyRestriction && hasRequestedLegacyExternalStorage;
+ return !shouldApplyRestriction && hasRequestedLegacyExternalStorage
+ && targetSDK <= Build.VERSION_CODES.Q;
}
@Override
public boolean mayDenyExtraAppOpIfGranted() {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index cf37bb5..65d0c4c 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -555,7 +555,7 @@
private RemoteAnimationDefinition mRemoteAnimationDefinition;
- private AnimatingActivityRegistry mAnimatingActivityRegistry;
+ AnimatingActivityRegistry mAnimatingActivityRegistry;
private Task mLastParent;
@@ -3088,7 +3088,7 @@
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
"Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
- getAnimation(), isAnimating(TRANSITION));
+ getAnimation(), isAnimating(TRANSITION | PARENTS));
ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
+ " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
@@ -3100,7 +3100,7 @@
// If this window was animating, then we need to ensure that the app transition notifies
// that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
// so add to that list now
- if (isAnimating(TRANSITION)) {
+ if (isAnimating(TRANSITION | PARENTS)) {
getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
}
@@ -3436,7 +3436,7 @@
* color mode set to avoid jank in the middle of the transition.
*/
boolean canShowWindows() {
- return allDrawn && !(isAnimating() && hasNonDefaultColorWindow());
+ return allDrawn && !(isAnimating(PARENTS) && hasNonDefaultColorWindow());
}
/**
@@ -5343,13 +5343,13 @@
if (!allDrawn && w.mightAffectAllDrawn()) {
if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
- + ", isAnimationSet=" + isAnimating(TRANSITION));
+ + ", isAnimationSet=" + isAnimating(TRANSITION | PARENTS));
if (!w.isDrawnLw()) {
Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
+ " pv=" + w.isVisibleByPolicy()
+ " mDrawState=" + winAnimator.drawStateToString()
+ " ph=" + w.isParentWindowHidden() + " th=" + mVisibleRequested
- + " a=" + isAnimating(TRANSITION));
+ + " a=" + isAnimating(TRANSITION | PARENTS));
}
}
@@ -5950,7 +5950,7 @@
@Override
void prepareSurfaces() {
- final boolean show = isVisible() || isAnimating();
+ final boolean show = isVisible() || isAnimating(PARENTS);
if (mSurfaceControl != null) {
if (show && !mLastSurfaceShowing) {
@@ -5978,7 +5978,7 @@
}
void attachThumbnailAnimation() {
- if (!isAnimating()) {
+ if (!isAnimating(PARENTS)) {
return;
}
final GraphicBuffer thumbnailHeader =
@@ -5998,7 +5998,7 @@
* {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
*/
void attachCrossProfileAppsThumbnailAnimation() {
- if (!isAnimating()) {
+ if (!isAnimating(PARENTS)) {
return;
}
clearThumbnail();
@@ -7516,7 +7516,7 @@
super.dumpDebug(proto, WINDOW_TOKEN, logLevel);
proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
- proto.write(IS_ANIMATING, isAnimating());
+ proto.write(IS_ANIMATING, isAnimating(PARENTS));
if (mThumbnail != null){
mThumbnail.dumpDebug(proto, THUMBNAIL);
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 814cb45..c959439 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -784,6 +784,10 @@
null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
null /* tempOtherTaskBounds */, null /* tempOtherTaskInsetBounds */,
PRESERVE_WINDOWS, true /* deferResume */);
+ } else if (overrideWindowingMode != WINDOWING_MODE_PINNED) {
+ // For pinned stack, resize is now part of the {@link WindowContainerTransaction}
+ resize(new Rect(newBounds), null /* tempTaskBounds */,
+ null /* tempTaskInsetBounds */, PRESERVE_WINDOWS, true /* deferResume */);
}
}
if (prevIsAlwaysOnTop != isAlwaysOnTop()) {
@@ -4888,6 +4892,18 @@
}
}
+ @Override
+ protected void onAnimationFinished() {
+ super.onAnimationFinished();
+ // TODO(b/142617871): we may need to add animation type parameter on onAnimationFinished to
+ // identify if the callback is for launch animation finish and then calling
+ // activity#onAnimationFinished.
+ final ActivityRecord activity = getTopMostActivity();
+ if (activity != null) {
+ activity.onAnimationFinished();
+ }
+ }
+
/**
* Sets the current picture-in-picture aspect ratio.
*/
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 3a33a3d..09111d0 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -436,9 +436,11 @@
mNextAppTransition = TRANSIT_UNSET;
mNextAppTransitionFlags = 0;
setAppTransitionState(APP_STATE_RUNNING);
- final AnimationAdapter topOpeningAnim = topOpeningApp != null
- ? topOpeningApp.getAnimation()
- : null;
+ final AnimationAdapter topOpeningAnim =
+ (topOpeningApp != null && topOpeningApp.getAnimatingContainer() != null)
+ ? topOpeningApp.getAnimatingContainer().getAnimation()
+ : null;
+
int redoLayout = notifyAppTransitionStartingLocked(transit,
topOpeningAnim != null ? topOpeningAnim.getDurationHint() : 0,
topOpeningAnim != null
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index fcab796..0b6a6e0 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3360,7 +3360,7 @@
// to look at all windows below the current target that are in this app, finding the
// highest visible one in layering.
WindowState highestTarget = null;
- if (activity.isAnimating(TRANSITION)) {
+ if (activity.isAnimating(PARENTS | TRANSITION)) {
highestTarget = activity.getHighestAnimLayerWindow(curTarget);
}
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 0b9be1a..6f7eeab 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -378,9 +378,10 @@
int getMode() {
final DisplayContent dc = mWindowContainer.getDisplayContent();
- if (dc.mOpeningApps.contains(mWindowContainer)) {
+ final ActivityRecord topActivity = mWindowContainer.getTopMostActivity();
+ if (dc.mOpeningApps.contains(topActivity)) {
return RemoteAnimationTarget.MODE_OPENING;
- } else if (dc.mChangingApps.contains(mWindowContainer)) {
+ } else if (dc.mChangingApps.contains(topActivity)) {
return RemoteAnimationTarget.MODE_CHANGING;
} else {
return RemoteAnimationTarget.MODE_CLOSING;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 914b95c..9a140da 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -94,6 +94,7 @@
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
import static java.lang.Integer.MAX_VALUE;
@@ -2555,6 +2556,16 @@
return getAppAnimationLayer(ANIMATION_LAYER_HOME);
}
+ @Override
+ Rect getAnimationBounds(int appStackClipMode) {
+ // TODO(b/131661052): we should remove appStackClipMode with hierarchical animations.
+ if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
+ // Using the stack bounds here effectively applies the clipping before animation.
+ return getStack().getBounds();
+ }
+ return super.getAnimationBounds(appStackClipMode);
+ }
+
boolean shouldAnimate() {
// Don't animate while the task runs recents animation but only if we are in the mode
// where we cancel with deferred screenshot, which means that the controller has
@@ -2568,6 +2579,18 @@
}
@Override
+ protected void onAnimationFinished() {
+ super.onAnimationFinished();
+ // TODO(b/142617871): we may need to add animation type parameter on onAnimationFinished to
+ // identify if the callback is for launch animation finish and then calling
+ // activity#onAnimationFinished.
+ final ActivityRecord activity = getTopMostActivity();
+ if (activity != null) {
+ activity.onAnimationFinished();
+ }
+ }
+
+ @Override
SurfaceControl.Builder makeSurface() {
return super.makeSurface().setMetadata(METADATA_TASK_ID, mTaskId);
}
@@ -2594,7 +2617,7 @@
@Override
RemoteAnimationTarget createRemoteAnimationTarget(
RemoteAnimationController.RemoteAnimationRecord record) {
- final ActivityRecord activity = getTopVisibleActivity();
+ final ActivityRecord activity = getTopMostActivity();
return activity != null ? activity.createRemoteAnimationTarget(record) : null;
}
@@ -2721,7 +2744,13 @@
getDimBounds(mTmpDimBoundsRect);
// Bounds need to be relative, as the dim layer is a child.
- mTmpDimBoundsRect.offsetTo(0, 0);
+ if (inFreeformWindowingMode()) {
+ getBounds(mTmpRect);
+ mTmpDimBoundsRect.offsetTo(mTmpDimBoundsRect.left - mTmpRect.left,
+ mTmpDimBoundsRect.top - mTmpRect.top);
+ } else {
+ mTmpDimBoundsRect.offsetTo(0, 0);
+ }
if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
scheduleAnimation();
}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 6ff4b2e..137d122 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -121,7 +121,7 @@
mFindResults.resetTopWallpaper = true;
if (w.mActivityRecord != null && !w.mActivityRecord.isVisible()
- && !w.mActivityRecord.isAnimating(TRANSITION)) {
+ && !w.mActivityRecord.isAnimating(TRANSITION | PARENTS)) {
// If this window's app token is hidden and not animating, it is of no interest to us.
if (DEBUG_WALLPAPER) Slog.v(TAG, "Skipping hidden and not animating token: " + w);
@@ -139,7 +139,7 @@
}
final boolean keyguardGoingAwayWithWallpaper = (w.mActivityRecord != null
- && w.mActivityRecord.isAnimating(TRANSITION)
+ && w.mActivityRecord.isAnimating(TRANSITION | PARENTS)
&& AppTransition.isKeyguardGoingAwayTransit(w.mActivityRecord.getTransit())
&& (w.mActivityRecord.getTransitFlags()
& TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
@@ -162,9 +162,11 @@
final RecentsAnimationController recentsAnimationController =
mService.getRecentsAnimationController();
- final boolean animationWallpaper = w.mActivityRecord != null
- && w.mActivityRecord.getAnimation() != null
- && w.mActivityRecord.getAnimation().getShowWallpaper();
+ final WindowContainer animatingContainer =
+ w.mActivityRecord != null ? w.mActivityRecord.getAnimatingContainer() : null;
+ final boolean animationWallpaper = animatingContainer != null
+ && animatingContainer.getAnimation() != null
+ && animatingContainer.getAnimation().getShowWallpaper();
final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0
|| animationWallpaper;
final boolean isRecentsTransitionTarget = (recentsAnimationController != null
@@ -228,14 +230,14 @@
if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
+ (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
+ " animating=" + ((wallpaperTarget != null && wallpaperTarget.mActivityRecord != null)
- ? wallpaperTarget.mActivityRecord.isAnimating(TRANSITION) : null)
+ ? wallpaperTarget.mActivityRecord.isAnimating(TRANSITION | PARENTS) : null)
+ " prev=" + mPrevWallpaperTarget
+ " recentsAnimationWallpaperVisible=" + isAnimatingWithRecentsComponent);
return (wallpaperTarget != null
&& (!wallpaperTarget.mObscured
|| isAnimatingWithRecentsComponent
|| (wallpaperTarget.mActivityRecord != null
- && wallpaperTarget.mActivityRecord.isAnimating(TRANSITION))))
+ && wallpaperTarget.mActivityRecord.isAnimating(TRANSITION | PARENTS))))
|| mPrevWallpaperTarget != null;
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 5daf567..cefef37 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -777,7 +777,7 @@
* otherwise.
*/
boolean isWaitingForTransitionStart() {
- return false;
+ return getActivity(app -> app.isWaitingForTransitionStart()) != null;
}
/**
@@ -785,7 +785,7 @@
* {@code ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise.
*/
boolean isAppTransitioning() {
- return getActivity(app -> app.isAnimating(TRANSITION)) != null;
+ return getActivity(app -> app.isAnimating(PARENTS | TRANSITION)) != null;
}
/**
@@ -1895,7 +1895,7 @@
if (adapter != null) {
startAnimation(getPendingTransaction(), adapter, !isVisible());
if (adapter.getShowWallpaper()) {
- mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
}
if (thumbnailAdapter != null) {
mThumbnail.startAnimation(
@@ -2040,7 +2040,8 @@
}
boolean okToDisplay() {
- return mDisplayContent != null && mDisplayContent.okToDisplay();
+ final DisplayContent dc = getDisplayContent();
+ return dc != null && dc.okToDisplay();
}
boolean okToAnimate() {
@@ -2048,7 +2049,8 @@
}
boolean okToAnimate(boolean ignoreFrozen) {
- return mDisplayContent != null && mDisplayContent.okToAnimate(ignoreFrozen);
+ final DisplayContent dc = getDisplayContent();
+ return dc != null && dc.okToAnimate(ignoreFrozen);
}
@Override
@@ -2090,6 +2092,21 @@
}
/**
+ * @return The {@link WindowContainer} which is running an animation.
+ *
+ * It traverses from the current container to its parents recursively. If nothing is animating,
+ * it will return {@code null}.
+ */
+ @Nullable
+ WindowContainer getAnimatingContainer() {
+ if (isAnimating()) {
+ return this;
+ }
+ final WindowContainer parent = getParent();
+ return (parent != null) ? parent.getAnimatingContainer() : null;
+ }
+
+ /**
* @see SurfaceAnimator#startDelayingAnimationStart
*/
void startDelayingAnimationStart() {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 00ef95a..4e768da 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -670,7 +670,7 @@
void updateRequestedInsetsState(InsetsState state) {
// Only update the sources the client is actually controlling.
- for (int i = state.getSourcesCount(); i >= 0; i--) {
+ for (int i = state.getSourcesCount() - 1; i >= 0; i--) {
final InsetsSource source = state.sourceAt(i);
mRequestedInsetsState.addSource(source);
}
@@ -984,8 +984,11 @@
final int layoutXDiff;
final int layoutYDiff;
final WindowState imeWin = mWmService.mRoot.getCurrentInputMethodWindow();
+ final boolean isInputMethodAdjustTarget = windowsAreFloating
+ ? dc.mInputMethodTarget != null && task == dc.mInputMethodTarget.getTask()
+ : isInputMethodTarget();
final boolean isImeTarget =
- imeWin != null && imeWin.isVisibleNow() && isInputMethodTarget();
+ imeWin != null && imeWin.isVisibleNow() && isInputMethodAdjustTarget;
if (isFullscreenAndFillsDisplay || layoutInParentFrame()) {
// We use the parent frame as the containing frame for fullscreen and child windows
mWindowFrames.mContainingFrame.set(mWindowFrames.mParentFrame);
@@ -1016,7 +1019,8 @@
final int distanceToTop = Math.max(mWindowFrames.mContainingFrame.top
- mWindowFrames.mContentFrame.top, 0);
int offs = Math.min(bottomOverlap, distanceToTop);
- mWindowFrames.mContainingFrame.top -= offs;
+ mWindowFrames.mContainingFrame.offset(0, -offs);
+ mInsetFrame.offset(0, -offs);
}
} else if (!inPinnedWindowingMode() && mWindowFrames.mContainingFrame.bottom
> mWindowFrames.mParentFrame.bottom) {
@@ -1586,7 +1590,7 @@
// TODO: Can we consolidate this with #isVisible() or have a more appropriate name for this?
boolean isWinVisibleLw() {
return (mActivityRecord == null || mActivityRecord.mVisibleRequested
- || mActivityRecord.isAnimating(TRANSITION)) && isVisible();
+ || mActivityRecord.isAnimating(TRANSITION | PARENTS)) && isVisible();
}
/**
@@ -1812,7 +1816,7 @@
// Starting window that's exiting will be removed when the animation finishes.
// Mark all relevant flags for that onExitAnimationDone will proceed all the way
// to actually remove it.
- if (!visible && isVisibleNow && mActivityRecord.isAnimating(TRANSITION)) {
+ if (!visible && isVisibleNow && mActivityRecord.isAnimating(PARENTS | TRANSITION)) {
mAnimatingExit = true;
mRemoveOnExit = true;
mWindowRemovalAllowed = true;
@@ -2081,7 +2085,7 @@
this, mWinAnimator.mSurfaceController, mAnimatingExit, mRemoveOnExit,
mHasSurface, mWinAnimator.getShown(),
isAnimating(TRANSITION | PARENTS),
- mActivityRecord != null && mActivityRecord.isAnimating(TRANSITION),
+ mActivityRecord != null && mActivityRecord.isAnimating(PARENTS | TRANSITION),
mWillReplaceWindow,
mWmService.mDisplayFrozen, Debug.getCallers(6));
@@ -4300,7 +4304,7 @@
+ " tok.visible=" + (mActivityRecord != null && mActivityRecord.isVisible())
+ " animating=" + isAnimating(TRANSITION | PARENTS)
+ " tok animating="
- + (mActivityRecord != null && mActivityRecord.isAnimating(TRANSITION))
+ + (mActivityRecord != null && mActivityRecord.isAnimating(TRANSITION | PARENTS))
+ " Callers=" + Debug.getCallers(4));
}
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 1a11766..486616d 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1398,7 +1398,7 @@
mWin.getDisplayContent().adjustForImeIfNeeded();
}
- return mWin.isAnimating(TRANSITION | PARENTS);
+ return mWin.isAnimating(PARENTS);
}
void dumpDebug(ProtoOutputStream proto, long fieldId) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 881ab8a..398ce50 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5807,8 +5807,9 @@
// Make sure that the caller is the profile owner or delegate.
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_CERT_INSTALL);
- // Verify that the profile owner was granted access to Device IDs.
- if (canProfileOwnerAccessDeviceIds(userId)) {
+ // Verify that the managed profile is on an organization-owned device and as such
+ // the profile owner can access Device IDs.
+ if (isProfileOwnerOfOrganizationOwnedDevice(userId)) {
return;
}
throw new SecurityException(
@@ -7725,7 +7726,13 @@
}
}
// Tell the user manager that the restrictions have changed.
- pushUserRestrictions(parent ? getProfileParentId(userHandle) : userHandle);
+ final int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle;
+ pushUserRestrictions(affectedUserId);
+
+ if (SecurityLog.isLoggingEnabled()) {
+ SecurityLog.writeEvent(SecurityLog.TAG_CAMERA_POLICY_SET,
+ who.getPackageName(), userHandle, affectedUserId, disabled ? 1 : 0);
+ }
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_CAMERA_DISABLED)
.setAdmin(who)
@@ -8005,7 +8012,7 @@
}
}
- private boolean canProfileOwnerAccessDeviceIds(int userId) {
+ private boolean isProfileOwnerOfOrganizationOwnedDevice(int userId) {
synchronized (getLockObject()) {
return mOwners.isProfileOwnerOfOrganizationOwnedDevice(userId);
}
@@ -8028,7 +8035,7 @@
}
private boolean isProfileOwnerOfOrganizationOwnedDevice(ComponentName who, int userId) {
- return isProfileOwner(who, userId) && canProfileOwnerAccessDeviceIds(userId);
+ return isProfileOwner(who, userId) && isProfileOwnerOfOrganizationOwnedDevice(userId);
}
@Override
@@ -8554,7 +8561,7 @@
for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
if (userInfo.isManagedProfile()) {
if (getProfileOwner(userInfo.id) != null
- && canProfileOwnerAccessDeviceIds(userInfo.id)) {
+ && isProfileOwnerOfOrganizationOwnedDevice(userInfo.id)) {
ComponentName who = getProfileOwner(userInfo.id);
return getActiveAdminUncheckedLocked(who, userInfo.id);
}
@@ -8605,7 +8612,7 @@
final boolean isCallerProfileOwnerOrDelegate = profileOwner != null
&& (profileOwner.getPackageName().equals(packageName)
|| isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL));
- if (isCallerProfileOwnerOrDelegate && canProfileOwnerAccessDeviceIds(userId)) {
+ if (isCallerProfileOwnerOrDelegate && isProfileOwnerOfOrganizationOwnedDevice(userId)) {
return true;
}
//TODO(b/130844684): Temporarily allow profile owner on non-organization-owned devices
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 0504d14..067f23a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server.appop;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
+import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME;
+import static android.app.AppOpsManager.FILTER_BY_UID;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
@@ -287,7 +289,7 @@
mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000);
- historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, sMyPackageName,
+ historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, sMyPackageName, null,
AppOpsManager.UID_STATE_PERSISTENT, 0, 1);
mAppOpsService.addHistoricalOps(historicalOps);
@@ -300,8 +302,8 @@
});
// First, do a fetch to ensure it's written
- mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, 0, Long.MAX_VALUE, 0,
- callback);
+ mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, null,
+ FILTER_BY_UID | FILTER_BY_PACKAGE_NAME, 0, Long.MAX_VALUE, 0, callback);
latchRef.get().await(5, TimeUnit.SECONDS);
assertThat(latchRef.get().getCount()).isEqualTo(0);
@@ -312,8 +314,8 @@
latchRef.set(new CountDownLatch(1));
- mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, 0, Long.MAX_VALUE, 0,
- callback);
+ mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, null,
+ FILTER_BY_UID | FILTER_BY_PACKAGE_NAME, 0, Long.MAX_VALUE, 0, callback);
latchRef.get().await(5, TimeUnit.SECONDS);
assertThat(latchRef.get().getCount()).isEqualTo(0);
diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/BinaryFileOperationsTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/BinaryFileOperationsTest.java
new file mode 100644
index 0000000..94f68a5
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/parser/BinaryFileOperationsTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.parser;
+
+import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
+import static com.android.server.integrity.parser.BinaryFileOperations.getBooleanValue;
+import static com.android.server.integrity.parser.BinaryFileOperations.getIntValue;
+import static com.android.server.integrity.parser.BinaryFileOperations.getStringValue;
+import static com.android.server.integrity.utils.TestUtils.getBits;
+import static com.android.server.integrity.utils.TestUtils.getBytes;
+import static com.android.server.integrity.utils.TestUtils.getValueBits;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.server.integrity.IntegrityUtils;
+import com.android.server.integrity.model.BitInputStream;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+
+@RunWith(JUnit4.class)
+public class BinaryFileOperationsTest {
+
+ private static final String IS_NOT_HASHED = "0";
+ private static final String IS_HASHED = "1";
+ private static final String PACKAGE_NAME = "com.test.app";
+ private static final String APP_CERTIFICATE = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+
+ @Test
+ public void testGetStringValue() throws IOException {
+ byte[] stringBytes =
+ getBytes(
+ IS_NOT_HASHED
+ + getBits(PACKAGE_NAME.length(), VALUE_SIZE_BITS)
+ + getValueBits(PACKAGE_NAME));
+ ByteBuffer rule = ByteBuffer.allocate(stringBytes.length);
+ rule.put(stringBytes);
+ BitInputStream inputStream = new BitInputStream(rule.array());
+
+ String resultString = getStringValue(inputStream);
+
+ assertThat(resultString).isEqualTo(PACKAGE_NAME);
+ }
+
+ @Test
+ public void testGetHashedStringValue() throws IOException {
+ byte[] ruleBytes =
+ getBytes(
+ IS_HASHED
+ + getBits(APP_CERTIFICATE.length(), VALUE_SIZE_BITS)
+ + getValueBits(APP_CERTIFICATE));
+ ByteBuffer rule = ByteBuffer.allocate(ruleBytes.length);
+ rule.put(ruleBytes);
+ BitInputStream inputStream = new BitInputStream(rule.array());
+
+ String resultString = getStringValue(inputStream);
+
+ assertThat(resultString)
+ .isEqualTo(IntegrityUtils.getHexDigest(
+ APP_CERTIFICATE.getBytes(StandardCharsets.UTF_8)));
+ }
+
+ @Test
+ public void testGetStringValue_withSizeAndHashingInfo() throws IOException {
+ byte[] ruleBytes = getBytes(getValueBits(PACKAGE_NAME));
+ ByteBuffer rule = ByteBuffer.allocate(ruleBytes.length);
+ rule.put(ruleBytes);
+ BitInputStream inputStream = new BitInputStream(rule.array());
+
+ String resultString = getStringValue(inputStream,
+ PACKAGE_NAME.length(), /* isHashedValue= */false);
+
+ assertThat(resultString).isEqualTo(PACKAGE_NAME);
+ }
+
+ @Test
+ public void testGetIntValue() throws IOException {
+ int randomValue = 15;
+ byte[] ruleBytes = getBytes(getBits(randomValue, /* numOfBits= */ 32));
+ ByteBuffer rule = ByteBuffer.allocate(ruleBytes.length);
+ rule.put(ruleBytes);
+ BitInputStream inputStream = new BitInputStream(rule.array());
+
+ assertThat(getIntValue(inputStream)).isEqualTo(randomValue);
+ }
+
+ @Test
+ public void testGetBooleanValue_true() throws IOException {
+ String booleanValue = "1";
+ byte[] ruleBytes = getBytes(booleanValue);
+ ByteBuffer rule = ByteBuffer.allocate(ruleBytes.length);
+ rule.put(ruleBytes);
+ BitInputStream inputStream = new BitInputStream(rule.array());
+
+ assertThat(getBooleanValue(inputStream)).isEqualTo(true);
+ }
+
+ @Test
+ public void testGetBooleanValue_false() throws IOException {
+ String booleanValue = "0";
+ byte[] ruleBytes = getBytes(booleanValue);
+ ByteBuffer rule = ByteBuffer.allocate(ruleBytes.length);
+ rule.put(ruleBytes);
+ BitInputStream inputStream = new BitInputStream(rule.array());
+
+ assertThat(getBooleanValue(inputStream)).isEqualTo(false);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
index 981db6a..eb6698b 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
@@ -27,6 +27,9 @@
import static com.android.server.integrity.model.ComponentBitSize.OPERATOR_BITS;
import static com.android.server.integrity.model.ComponentBitSize.SEPARATOR_BITS;
import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
+import static com.android.server.integrity.model.IndexingFileConstants.END_INDEXING_KEY;
+import static com.android.server.integrity.model.IndexingFileConstants.INDEXING_BLOCK_SIZE;
+import static com.android.server.integrity.model.IndexingFileConstants.START_INDEXING_KEY;
import static com.android.server.integrity.utils.TestUtils.getBits;
import static com.android.server.integrity.utils.TestUtils.getBytes;
import static com.android.server.integrity.utils.TestUtils.getValueBits;
@@ -94,6 +97,15 @@
private static final byte[] DEFAULT_FORMAT_VERSION_BYTES =
getBytes(getBits(DEFAULT_FORMAT_VERSION, FORMAT_VERSION_BITS));
+ private static final String SERIALIZED_START_INDEXING_KEY =
+ IS_NOT_HASHED
+ + getBits(START_INDEXING_KEY.length(), VALUE_SIZE_BITS)
+ + getValueBits(START_INDEXING_KEY);
+ private static final String SERIALIZED_END_INDEXING_KEY =
+ IS_NOT_HASHED
+ + getBits(END_INDEXING_KEY.length(), VALUE_SIZE_BITS)
+ + getValueBits(END_INDEXING_KEY);
+
@Test
public void testBinaryString_serializeNullRules() {
RuleSerializer binarySerializer = new RuleBinarySerializer();
@@ -107,15 +119,34 @@
@Test
public void testBinaryString_emptyRules() throws Exception {
- ByteArrayOutputStream expectedArrayOutputStream = new ByteArrayOutputStream();
- expectedArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
-
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream();
+ ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream();
RuleSerializer binarySerializer = new RuleBinarySerializer();
- binarySerializer.serialize(
- Collections.emptyList(), /* formatVersion= */ Optional.empty(), outputStream);
- assertThat(outputStream.toByteArray()).isEqualTo(expectedArrayOutputStream.toByteArray());
+ binarySerializer.serialize(
+ Collections.emptyList(),
+ /* formatVersion= */ Optional.empty(),
+ ruleOutputStream,
+ indexingOutputStream);
+
+ ByteArrayOutputStream expectedRuleOutputStream = new ByteArrayOutputStream();
+ expectedRuleOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
+ assertThat(ruleOutputStream.toByteArray())
+ .isEqualTo(expectedRuleOutputStream.toByteArray());
+
+ ByteArrayOutputStream expectedIndexingOutputStream = new ByteArrayOutputStream();
+ byte[] expectedIndexingBytes =
+ getBytes(
+ SERIALIZED_START_INDEXING_KEY
+ + getBits(DEFAULT_FORMAT_VERSION_BYTES.length, /* numOfBits= */ 32)
+ + SERIALIZED_END_INDEXING_KEY
+ + getBits(DEFAULT_FORMAT_VERSION_BYTES.length, /* numOfBits= */
+ 32));
+ expectedIndexingOutputStream.write(expectedIndexingBytes);
+ expectedIndexingOutputStream.write(expectedIndexingBytes);
+ expectedIndexingOutputStream.write(expectedIndexingBytes);
+ assertThat(indexingOutputStream.toByteArray())
+ .isEqualTo(expectedIndexingOutputStream.toByteArray());
}
@Test
@@ -131,8 +162,16 @@
packageName,
/* isHashedValue= */ false))),
Rule.DENY);
+
+ ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream();
+ ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream();
RuleSerializer binarySerializer = new RuleBinarySerializer();
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ binarySerializer.serialize(
+ Collections.singletonList(rule),
+ /* formatVersion= */ Optional.empty(),
+ ruleOutputStream,
+ indexingOutputStream);
+
String expectedBits =
START_BIT
+ COMPOUND_FORMULA_START_BITS
@@ -146,18 +185,29 @@
+ COMPOUND_FORMULA_END_BITS
+ DENY
+ END_BIT;
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
- byteArrayOutputStream.write(getBytes(expectedBits));
- byte[] expectedRules = byteArrayOutputStream.toByteArray();
+ ByteArrayOutputStream expectedRuleOutputStream = new ByteArrayOutputStream();
+ expectedRuleOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
+ expectedRuleOutputStream.write(getBytes(expectedBits));
+ assertThat(ruleOutputStream.toByteArray())
+ .isEqualTo(expectedRuleOutputStream.toByteArray());
- binarySerializer.serialize(
- Collections.singletonList(rule),
- /* formatVersion= */ Optional.empty(),
- outputStream);
-
- byte[] actualRules = outputStream.toByteArray();
- assertThat(actualRules).isEqualTo(expectedRules);
+ ByteArrayOutputStream expectedIndexingOutputStream = new ByteArrayOutputStream();
+ String expectedIndexingBitsForIndexed =
+ SERIALIZED_START_INDEXING_KEY
+ + getBits(DEFAULT_FORMAT_VERSION_BYTES.length, /* numOfBits= */ 32)
+ + SERIALIZED_END_INDEXING_KEY
+ + getBits(DEFAULT_FORMAT_VERSION_BYTES.length, /* numOfBits= */ 32);
+ expectedIndexingOutputStream.write(getBytes(expectedIndexingBitsForIndexed));
+ expectedIndexingOutputStream.write(getBytes(expectedIndexingBitsForIndexed));
+ String expectedIndexingBitsForUnindexed =
+ SERIALIZED_START_INDEXING_KEY
+ + getBits(DEFAULT_FORMAT_VERSION_BYTES.length, /* numOfBits= */ 32)
+ + SERIALIZED_END_INDEXING_KEY
+ + getBits(DEFAULT_FORMAT_VERSION_BYTES.length + getBytes(
+ expectedBits).length, /* numOfBits= */ 32);
+ expectedIndexingOutputStream.write(getBytes(expectedIndexingBitsForUnindexed));
+ assertThat(indexingOutputStream.toByteArray())
+ .isEqualTo(expectedIndexingOutputStream.toByteArray());
}
@Test
@@ -453,91 +503,113 @@
}
@Test
- public void testBinaryString_serializeComplexCompoundFormula_indexingOrderValid()
- throws Exception {
- String packageNameA = "aaa";
- String packageNameB = "bbb";
- String packageNameC = "ccc";
- String appCert1 = "cert1";
- String appCert2 = "cert2";
- String appCert3 = "cert3";
- Rule installerRule =
- new Rule(
- new CompoundFormula(
- CompoundFormula.AND,
- Arrays.asList(
- new AtomicFormula.StringAtomicFormula(
- AtomicFormula.INSTALLER_NAME,
- SAMPLE_INSTALLER_NAME,
- /* isHashedValue= */ false),
- new AtomicFormula.StringAtomicFormula(
- AtomicFormula.INSTALLER_CERTIFICATE,
- SAMPLE_INSTALLER_CERT,
- /* isHashedValue= */ false))),
- Rule.DENY);
+ public void testBinaryString_verifyManyRulesAreIndexedCorrectly() throws Exception {
+ int ruleCount = 225;
+ String packagePrefix = "package.name.";
+ String appCertificatePrefix = "app.cert.";
+ String installerNamePrefix = "installer.";
- RuleSerializer binarySerializer = new RuleBinarySerializer();
+ // Create the rule set with 225 package name based rules, 225 app certificate indexed rules,
+ // and 225 non-indexed rules..
List<Rule> ruleList = new ArrayList();
- ruleList.add(getRuleWithAppCertificateAndSampleInstallerName(appCert3));
- ruleList.add(getRuleWithAppCertificateAndSampleInstallerName(appCert2));
- ruleList.add(getRuleWithAppCertificateAndSampleInstallerName(appCert1));
- ruleList.add(getRuleWithPackageNameAndSampleInstallerName(packageNameB));
- ruleList.add(getRuleWithPackageNameAndSampleInstallerName(packageNameC));
- ruleList.add(getRuleWithPackageNameAndSampleInstallerName(packageNameA));
- ruleList.add(installerRule);
- byte[] actualRules =
- binarySerializer.serialize(ruleList, /* formatVersion= */ Optional.empty());
+ for (int count = 0; count < ruleCount; count++) {
+ ruleList.add(getRuleWithPackageNameAndSampleInstallerName(
+ String.format("%s%04d", packagePrefix, count)));
+ }
+ for (int count = 0; count < ruleCount; count++) {
+ ruleList.add(getRuleWithAppCertificateAndSampleInstallerName(
+ String.format("%s%04d", appCertificatePrefix, count)));
+ }
+ for (int count = 0; count < ruleCount; count++) {
+ ruleList.add(getNonIndexedRuleWithInstallerName(
+ String.format("%s%04d", installerNamePrefix, count)));
+ }
- // Note that ordering is important here and the test verifies that the rules are written
- // in this sorted order.
- ByteArrayOutputStream expectedArrayOutputStream = new ByteArrayOutputStream();
- expectedArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
- expectedArrayOutputStream.write(
- getBytes(
- getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(
- packageNameA)));
- expectedArrayOutputStream.write(
- getBytes(
- getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(
- packageNameB)));
- expectedArrayOutputStream.write(
- getBytes(
- getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(
- packageNameC)));
- expectedArrayOutputStream.write(
- getBytes(
- getSerializedCompoundRuleWithCertificateNameAndSampleInstallerName(
- appCert1)));
- expectedArrayOutputStream.write(
- getBytes(
- getSerializedCompoundRuleWithCertificateNameAndSampleInstallerName(
- appCert2)));
- expectedArrayOutputStream.write(
- getBytes(
- getSerializedCompoundRuleWithCertificateNameAndSampleInstallerName(
- appCert3)));
- String expectedBitsForInstallerRule =
- START_BIT
- + COMPOUND_FORMULA_START_BITS
- + AND
- + ATOMIC_FORMULA_START_BITS
- + INSTALLER_NAME
- + EQ
- + IS_NOT_HASHED
- + getBits(SAMPLE_INSTALLER_NAME.length(), VALUE_SIZE_BITS)
- + getValueBits(SAMPLE_INSTALLER_NAME)
- + ATOMIC_FORMULA_START_BITS
- + INSTALLER_CERTIFICATE
- + EQ
- + IS_NOT_HASHED
- + getBits(SAMPLE_INSTALLER_CERT.length(), VALUE_SIZE_BITS)
- + getValueBits(SAMPLE_INSTALLER_CERT)
- + COMPOUND_FORMULA_END_BITS
- + DENY
- + END_BIT;
- expectedArrayOutputStream.write(getBytes(expectedBitsForInstallerRule));
+ // Serialize the rules.
+ ByteArrayOutputStream ruleOutputStream = new ByteArrayOutputStream();
+ ByteArrayOutputStream indexingOutputStream = new ByteArrayOutputStream();
+ RuleSerializer binarySerializer = new RuleBinarySerializer();
+ binarySerializer.serialize(
+ ruleList,
+ /* formatVersion= */ Optional.empty(),
+ ruleOutputStream,
+ indexingOutputStream);
- assertThat(actualRules).isEqualTo(expectedArrayOutputStream.toByteArray());
+ // Verify the rules file and index files.
+ ByteArrayOutputStream expectedOrderedRuleOutputStream = new ByteArrayOutputStream();
+ ByteArrayOutputStream expectedIndexingOutputStream = new ByteArrayOutputStream();
+
+ expectedOrderedRuleOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
+ int totalBytesWritten = DEFAULT_FORMAT_VERSION_BYTES.length;
+
+ String expectedIndexingBytesForPackageNameIndexed =
+ SERIALIZED_START_INDEXING_KEY
+ + getBits(totalBytesWritten, /* numOfBits= */ 32);
+ for (int count = 0; count < ruleCount; count++) {
+ String packageName = String.format("%s%04d", packagePrefix, count);
+ if (count > 0 && count % INDEXING_BLOCK_SIZE == 0) {
+ expectedIndexingBytesForPackageNameIndexed +=
+ IS_NOT_HASHED
+ + getBits(packageName.length(), VALUE_SIZE_BITS)
+ + getValueBits(packageName)
+ + getBits(totalBytesWritten, /* numOfBits= */ 32);
+ }
+
+ byte[] bytesForPackage =
+ getBytes(getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(
+ packageName));
+ expectedOrderedRuleOutputStream.write(bytesForPackage);
+ totalBytesWritten += bytesForPackage.length;
+ }
+ expectedIndexingBytesForPackageNameIndexed +=
+ SERIALIZED_END_INDEXING_KEY
+ + getBits(totalBytesWritten, /* numOfBits= */ 32);
+ expectedIndexingOutputStream.write(getBytes(expectedIndexingBytesForPackageNameIndexed));
+
+ String expectedIndexingBytesForAppCertificateIndexed =
+ SERIALIZED_START_INDEXING_KEY
+ + getBits(totalBytesWritten, /* numOfBits= */ 32);
+ for (int count = 0; count < ruleCount; count++) {
+ String appCertificate = String.format("%s%04d", appCertificatePrefix, count);
+ if (count > 0 && count % INDEXING_BLOCK_SIZE == 0) {
+ expectedIndexingBytesForAppCertificateIndexed +=
+ IS_NOT_HASHED
+ + getBits(appCertificate.length(), VALUE_SIZE_BITS)
+ + getValueBits(appCertificate)
+ + getBits(totalBytesWritten, /* numOfBits= */ 32);
+ }
+
+ byte[] bytesForPackage =
+ getBytes(getSerializedCompoundRuleWithCertificateNameAndSampleInstallerName(
+ appCertificate));
+ expectedOrderedRuleOutputStream.write(bytesForPackage);
+ totalBytesWritten += bytesForPackage.length;
+ }
+ expectedIndexingBytesForAppCertificateIndexed +=
+ SERIALIZED_END_INDEXING_KEY
+ + getBits(totalBytesWritten, /* numOfBits= */ 32);
+ expectedIndexingOutputStream.write(getBytes(expectedIndexingBytesForAppCertificateIndexed));
+
+ String expectedIndexingBytesForUnindexed =
+ SERIALIZED_START_INDEXING_KEY
+ + getBits(totalBytesWritten, /* numOfBits= */ 32);
+ for (int count = 0; count < ruleCount; count++) {
+ byte[] bytesForPackage =
+ getBytes(getSerializedCompoundRuleWithInstallerNameAndInstallerCert(
+ String.format("%s%04d", installerNamePrefix, count)));
+ expectedOrderedRuleOutputStream.write(bytesForPackage);
+ totalBytesWritten += bytesForPackage.length;
+ }
+ expectedIndexingBytesForUnindexed +=
+ SERIALIZED_END_INDEXING_KEY
+ + getBits(totalBytesWritten, /* numOfBits= */ 32);
+ expectedIndexingOutputStream.write(getBytes(expectedIndexingBytesForUnindexed));
+
+
+ assertThat(ruleOutputStream.toByteArray())
+ .isEqualTo(expectedOrderedRuleOutputStream.toByteArray());
+ assertThat(indexingOutputStream.toByteArray())
+ .isEqualTo(expectedIndexingOutputStream.toByteArray());
}
private Rule getRuleWithPackageNameAndSampleInstallerName(String packageName) {
@@ -616,6 +688,44 @@
+ END_BIT;
}
+ private Rule getNonIndexedRuleWithInstallerName(String installerName) {
+ return new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ installerName,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_CERTIFICATE,
+ SAMPLE_INSTALLER_CERT,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+ }
+
+ private String getSerializedCompoundRuleWithInstallerNameAndInstallerCert(
+ String installerName) {
+ return START_BIT
+ + COMPOUND_FORMULA_START_BITS
+ + AND
+ + ATOMIC_FORMULA_START_BITS
+ + INSTALLER_NAME
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(installerName.length(), VALUE_SIZE_BITS)
+ + getValueBits(installerName)
+ + ATOMIC_FORMULA_START_BITS
+ + INSTALLER_CERTIFICATE
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(SAMPLE_INSTALLER_CERT.length(), VALUE_SIZE_BITS)
+ + getValueBits(SAMPLE_INSTALLER_CERT)
+ + COMPOUND_FORMULA_END_BITS
+ + DENY
+ + END_BIT;
+ }
+
private static Formula getInvalidFormula() {
return new Formula() {
@Override
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
index 0bb2d44..ff7722c 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
@@ -145,7 +145,8 @@
xmlSerializer.serialize(
Collections.singletonList(rule),
/* formatVersion= */ Optional.empty(),
- outputStream);
+ outputStream,
+ new ByteArrayOutputStream());
byte[] actualRules = outputStream.toString().getBytes(StandardCharsets.UTF_8);
assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 248b06b..d3cd3cb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -21,6 +21,7 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.view.WindowManager.TRANSIT_TASK_OPEN;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyFloat;
@@ -49,7 +50,12 @@
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.IRemoteAnimationFinishedCallback;
+import android.view.IRemoteAnimationRunner;
+import android.view.RemoteAnimationAdapter;
+import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -782,6 +788,63 @@
assertEquals(newDc, activity.mDisplayContent);
}
+ @Test
+ public void testTaskCanApplyAnimation() {
+ final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
+ final Task task = createTaskInStack(stack, 0 /* userId */);
+ final ActivityRecord activity =
+ WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
+ verifyWindowContainerApplyAnimation(task, activity);
+ }
+
+ @Test
+ public void testStackCanApplyAnimation() {
+ final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
+ final ActivityRecord activity = WindowTestUtils.createActivityRecordInTask(mDisplayContent,
+ createTaskInStack(stack, 0 /* userId */));
+ verifyWindowContainerApplyAnimation(stack, activity);
+ }
+
+ private void verifyWindowContainerApplyAnimation(WindowContainer wc, ActivityRecord act) {
+ // Initial remote animation for app transition.
+ final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
+ new IRemoteAnimationRunner.Stub() {
+ @Override
+ public void onAnimationStart(RemoteAnimationTarget[] apps,
+ RemoteAnimationTarget[] wallpapers,
+ IRemoteAnimationFinishedCallback finishedCallback) {
+ try {
+ finishedCallback.onAnimationFinished();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onAnimationCancelled() {
+ }
+ }, 0, 0, false);
+ adapter.setCallingPidUid(123, 456);
+ wc.getDisplayContent().prepareAppTransition(TRANSIT_TASK_OPEN, false);
+ wc.getDisplayContent().mAppTransition.overridePendingAppTransitionRemote(adapter);
+ spyOn(wc);
+ doReturn(true).when(wc).okToAnimate();
+
+ // Make sure animating state is as expected after applied animation.
+ assertTrue(wc.applyAnimation(null, TRANSIT_TASK_OPEN, true, false));
+ assertEquals(wc.getTopMostActivity(), act);
+ assertTrue(wc.isAnimating());
+ assertTrue(act.isAnimating(PARENTS));
+
+ // Make sure animation finish callback will be received and reset animating state after
+ // animation finish.
+ wc.getDisplayContent().mAppTransition.goodToGo(TRANSIT_TASK_OPEN, act,
+ mDisplayContent.mOpeningApps);
+ verify(wc).onAnimationFinished();
+ assertFalse(wc.isAnimating());
+ assertFalse(act.isAnimating(PARENTS));
+ }
+
/* Used so we can gain access to some protected members of the {@link WindowContainer} class */
private static class TestWindowContainer extends WindowContainer<TestWindowContainer> {
private final int mLayer;
diff --git a/services/usage/OWNERS b/services/usage/OWNERS
new file mode 100644
index 0000000..9daa093
--- /dev/null
+++ b/services/usage/OWNERS
@@ -0,0 +1,4 @@
+mwachens@google.com
+varunshah@google.com
+huiyu@google.com
+yamasani@google.com
diff --git a/telephony/common/com/android/internal/telephony/EncodeException.java b/telephony/common/com/android/internal/telephony/EncodeException.java
index cdc853e..bb723a0 100644
--- a/telephony/common/com/android/internal/telephony/EncodeException.java
+++ b/telephony/common/com/android/internal/telephony/EncodeException.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* {@hide}
diff --git a/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java b/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java
index 922af12..0b47547 100644
--- a/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java
+++ b/telephony/common/com/android/internal/telephony/PackageChangeReceiver.java
@@ -24,17 +24,17 @@
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.UserHandle;
-import com.android.internal.os.BackgroundThread;
-
/**
* Helper class for monitoring the state of packages: adding, removing,
* updating, and disappearing and reappearing on the SD card.
*/
public abstract class PackageChangeReceiver extends BroadcastReceiver {
static final IntentFilter sPackageIntentFilter = new IntentFilter();
+ private static HandlerThread sHandlerThread;
static {
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -43,28 +43,24 @@
sPackageIntentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
sPackageIntentFilter.addDataScheme("package");
}
+ // Keep an instance of Context around as long as we still want the receiver:
+ // if the instance of Context gets garbage-collected, it'll unregister the receiver, so only
+ // unset when we want to unregister.
Context mRegisteredContext;
/**
- * To register the intents that needed for monitoring the state of packages
+ * To register the intents that needed for monitoring the state of packages. Once this method
+ * has been called on an instance of {@link PackageChangeReceiver}, all subsequent calls must
+ * have the same {@code user} argument.
*/
public void register(@NonNull Context context, @Nullable Looper thread,
@Nullable UserHandle user) {
if (mRegisteredContext != null) {
throw new IllegalStateException("Already registered");
}
- Handler handler = (thread == null) ? BackgroundThread.getHandler() : new Handler(thread);
- mRegisteredContext = context;
- if (handler != null) {
- if (user != null) {
- context.registerReceiverAsUser(this, user, sPackageIntentFilter, null, handler);
- } else {
- context.registerReceiver(this, sPackageIntentFilter,
- null, handler);
- }
- } else {
- throw new NullPointerException();
- }
+ Handler handler = new Handler(thread == null ? getStaticLooper() : thread);
+ mRegisteredContext = user == null ? context : context.createContextAsUser(user, 0);
+ mRegisteredContext.registerReceiver(this, sPackageIntentFilter, null, handler);
}
/**
@@ -78,6 +74,14 @@
mRegisteredContext = null;
}
+ private static synchronized Looper getStaticLooper() {
+ if (sHandlerThread == null) {
+ sHandlerThread = new HandlerThread(PackageChangeReceiver.class.getSimpleName());
+ sHandlerThread.start();
+ }
+ return sHandlerThread.getLooper();
+ }
+
/**
* This method is invoked when receive the Intent.ACTION_PACKAGE_ADDED
*/
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index 0275cb9..b302589 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -58,6 +58,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
/**
* Class for managing the primary application that we will deliver SMS/MMS messages to
@@ -248,6 +249,7 @@
private static Collection<SmsApplicationData> getApplicationCollectionInternal(
Context context, int userId) {
PackageManager packageManager = context.getPackageManager();
+ UserHandle userHandle = UserHandle.of(userId);
// Get the list of apps registered for SMS
Intent intent = new Intent(Intents.SMS_DELIVER_ACTION);
@@ -256,7 +258,7 @@
}
List<ResolveInfo> smsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- userId);
+ userHandle);
HashMap<String, SmsApplicationData> receivers = new HashMap<String, SmsApplicationData>();
@@ -283,7 +285,7 @@
intent.setDataAndType(null, "application/vnd.wap.mms-message");
List<ResolveInfo> mmsReceivers = packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- userId);
+ userHandle);
for (ResolveInfo resolveInfo : mmsReceivers) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
if (activityInfo == null) {
@@ -325,7 +327,7 @@
Uri.fromParts(SCHEME_SMSTO, "", null));
List<ResolveInfo> sendToActivities = packageManager.queryIntentActivitiesAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- userId);
+ userHandle);
for (ResolveInfo resolveInfo : sendToActivities) {
final ActivityInfo activityInfo = resolveInfo.activityInfo;
if (activityInfo == null) {
@@ -343,7 +345,7 @@
List<ResolveInfo> smsAppChangedReceivers =
packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
if (DEBUG_MULTIUSER) {
Log.i(LOG_TAG, "getApplicationCollectionInternal smsAppChangedActivities=" +
smsAppChangedReceivers);
@@ -370,7 +372,7 @@
List<ResolveInfo> providerChangedReceivers =
packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
if (DEBUG_MULTIUSER) {
Log.i(LOG_TAG, "getApplicationCollectionInternal providerChangedActivities=" +
providerChangedReceivers);
@@ -397,7 +399,7 @@
List<ResolveInfo> simFullReceivers =
packageManager.queryBroadcastReceiversAsUser(intent,
PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
if (DEBUG_MULTIUSER) {
Log.i(LOG_TAG, "getApplicationCollectionInternal simFullReceivers="
+ simFullReceivers);
@@ -626,7 +628,8 @@
}
// We only make the change if the new package is valid
- PackageManager packageManager = context.getPackageManager();
+ PackageManager packageManager =
+ context.createContextAsUser(userHandle, 0).getPackageManager();
Collection<SmsApplicationData> applications = getApplicationCollectionInternal(
context, userId);
SmsApplicationData oldAppData = oldPackageName != null ?
@@ -637,8 +640,7 @@
AppOpsManager appOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
if (oldPackageName != null) {
try {
- int uid = packageManager.getPackageInfoAsUser(
- oldPackageName, 0, userId).applicationInfo.uid;
+ int uid = packageManager.getPackageInfo(oldPackageName, 0).applicationInfo.uid;
setExclusiveAppops(oldPackageName, appOps, uid, AppOpsManager.MODE_DEFAULT);
} catch (NameNotFoundException e) {
Rlog.w(LOG_TAG, "Old SMS package not found: " + oldPackageName);
@@ -802,9 +804,16 @@
}
private void onPackageChanged() {
- PackageManager packageManager = mContext.getPackageManager();
+ int userId;
+ try {
+ userId = getSendingUser().getIdentifier();
+ } catch (NullPointerException e) {
+ // This should never happen in prod -- unit tests will put the receiver into a
+ // unusual state where the pending result is null, which produces a NPE when calling
+ // getSendingUserId. Just pretend like it's the system user for testing.
+ userId = UserHandle.USER_SYSTEM;
+ }
Context userContext = mContext;
- final int userId = getSendingUserId();
if (userId != UserHandle.USER_SYSTEM) {
try {
userContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
@@ -815,10 +824,11 @@
}
}
}
+ PackageManager packageManager = userContext.getPackageManager();
// Ensure this component is still configured as the preferred activity
ComponentName componentName = getDefaultSendToApplication(userContext, true);
if (componentName != null) {
- configurePreferredActivity(packageManager, componentName, userId);
+ configurePreferredActivity(packageManager, componentName);
}
}
}
@@ -830,41 +840,36 @@
@UnsupportedAppUsage
private static void configurePreferredActivity(PackageManager packageManager,
- ComponentName componentName, int userId) {
+ ComponentName componentName) {
// Add the four activity preferences we want to direct to this app.
- replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMS);
- replacePreferredActivity(packageManager, componentName, userId, SCHEME_SMSTO);
- replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMS);
- replacePreferredActivity(packageManager, componentName, userId, SCHEME_MMSTO);
+ replacePreferredActivity(packageManager, componentName, SCHEME_SMS);
+ replacePreferredActivity(packageManager, componentName, SCHEME_SMSTO);
+ replacePreferredActivity(packageManager, componentName, SCHEME_MMS);
+ replacePreferredActivity(packageManager, componentName, SCHEME_MMSTO);
}
/**
* Updates the ACTION_SENDTO activity to the specified component for the specified scheme.
*/
private static void replacePreferredActivity(PackageManager packageManager,
- ComponentName componentName, int userId, String scheme) {
+ ComponentName componentName, String scheme) {
// Build the set of existing activities that handle this scheme
Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(scheme, "", null));
- List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivitiesAsUser(
- intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER,
- userId);
+ List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(
+ intent, PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_RESOLVED_FILTER);
- // Build the set of ComponentNames for these activities
- final int n = resolveInfoList.size();
- ComponentName[] set = new ComponentName[n];
- for (int i = 0; i < n; i++) {
- ResolveInfo info = resolveInfoList.get(i);
- set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
- }
+ List<ComponentName> components = resolveInfoList.stream().map(info ->
+ new ComponentName(info.activityInfo.packageName, info.activityInfo.name))
+ .collect(Collectors.toList());
// Update the preferred SENDTO activity for the specified scheme
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SENDTO);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
intentFilter.addDataScheme(scheme);
- packageManager.replacePreferredActivityAsUser(intentFilter,
+ packageManager.replacePreferredActivity(intentFilter,
IntentFilter.MATCH_CATEGORY_SCHEME + IntentFilter.MATCH_ADJUSTMENT_NORMAL,
- set, componentName, userId);
+ components, componentName);
}
/**
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index e523fba..ce32dce 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -185,6 +185,14 @@
@SystemApi
public abstract @NonNull CellLocation asCellLocation();
+ /**
+ * Create and a return a new instance of CellIdentity with location-identifying information
+ * removed.
+ *
+ * @hide
+ */
+ public abstract @NonNull CellIdentity sanitizeLocationInfo();
+
@Override
public boolean equals(Object other) {
if (!(other instanceof CellIdentity)) {
@@ -312,4 +320,23 @@
return true;
}
+ /** @hide */
+ public static CellIdentity create(android.hardware.radio.V1_5.CellIdentity ci) {
+ if (ci == null) return null;
+ switch (ci.getDiscriminator()) {
+ case android.hardware.radio.V1_5.CellIdentity.hidl_discriminator.gsm:
+ return new CellIdentityGsm(ci.gsm());
+ case android.hardware.radio.V1_5.CellIdentity.hidl_discriminator.cdma:
+ return new CellIdentityCdma(ci.cdma());
+ case android.hardware.radio.V1_5.CellIdentity.hidl_discriminator.lte:
+ return new CellIdentityLte(ci.lte());
+ case android.hardware.radio.V1_5.CellIdentity.hidl_discriminator.wcdma:
+ return new CellIdentityWcdma(ci.wcdma());
+ case android.hardware.radio.V1_5.CellIdentity.hidl_discriminator.tdscdma:
+ return new CellIdentityTdscdma(ci.tdscdma());
+ case android.hardware.radio.V1_5.CellIdentity.hidl_discriminator.nr:
+ return new CellIdentityNr(ci.nr());
+ default: return null;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 54236b42..1a6bf33 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -128,7 +128,8 @@
}
/** @hide */
- public CellIdentityCdma sanitizeLocationInfo() {
+ @Override
+ public @NonNull CellIdentityCdma sanitizeLocationInfo() {
return new CellIdentityCdma(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
mAlphaLong, mAlphaShort);
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 4e4454d..2ecdfce 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -104,7 +104,8 @@
}
/** @hide */
- public CellIdentityGsm sanitizeLocationInfo() {
+ @Override
+ public @NonNull CellIdentityGsm sanitizeLocationInfo() {
return new CellIdentityGsm(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
CellInfo.UNAVAILABLE, mMccStr, mMncStr, mAlphaLong, mAlphaShort);
}
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index c3fc73b..15c9175 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -121,7 +121,8 @@
}
/** @hide */
- public CellIdentityLte sanitizeLocationInfo() {
+ @Override
+ public @NonNull CellIdentityLte sanitizeLocationInfo() {
return new CellIdentityLte(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
mMccStr, mMncStr, mAlphaLong, mAlphaShort);
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index e3fec7b..f08a580 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -69,7 +69,8 @@
}
/** @hide */
- public CellIdentityNr sanitizeLocationInfo() {
+ @Override
+ public @NonNull CellIdentityNr sanitizeLocationInfo() {
return new CellIdentityNr(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
mMccStr, mMncStr, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort);
}
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 8f812b6..4bb3a95 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -97,7 +97,8 @@
}
/** @hide */
- public CellIdentityTdscdma sanitizeLocationInfo() {
+ @Override
+ public @NonNull CellIdentityTdscdma sanitizeLocationInfo() {
return new CellIdentityTdscdma(mMccStr, mMncStr, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort);
}
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 556bc32..4ecd134 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
@@ -98,7 +98,8 @@
}
/** @hide */
- public CellIdentityWcdma sanitizeLocationInfo() {
+ @Override
+ public @NonNull CellIdentityWcdma sanitizeLocationInfo() {
return new CellIdentityWcdma(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mMccStr, mMncStr,
mAlphaLong, mAlphaShort);
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index ae45307..475c99b 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -18,7 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.radio.V1_4.CellInfo.Info;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
index 30b131f..2b1387c 100644
--- a/telephony/java/android/telephony/CellInfoCdma.java
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -17,11 +17,10 @@
package android.telephony;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
/**
* A {@link CellInfo} representing a CDMA cell that provides identity and measurement info.
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
index 137f97e..4f7c7a9 100644
--- a/telephony/java/android/telephony/CellInfoGsm.java
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -17,10 +17,9 @@
package android.telephony;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
/**
* A {@link CellInfo} representing a GSM cell that provides identity and measurement info.
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index da7b7ab..6d19261 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -17,7 +17,7 @@
package android.telephony;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java
index 0133153..64776e3 100644
--- a/telephony/java/android/telephony/CellLocation.java
+++ b/telephony/java/android/telephony/CellLocation.java
@@ -16,13 +16,13 @@
package android.telephony;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
-
-import android.annotation.UnsupportedAppUsage;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
+
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.PhoneConstants;
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index fb16d54..a9f3487 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -17,12 +17,11 @@
package android.telephony;
import android.annotation.IntRange;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
-import android.telephony.Rlog;
import java.util.Objects;
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 8df9d23..a6ba9c2 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -17,7 +17,7 @@
package android.telephony;
import android.annotation.IntRange;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index 4dc54f0..34b1385 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -18,11 +18,10 @@
import android.annotation.IntRange;
import android.annotation.StringDef;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
-import android.telephony.Rlog;
import android.text.TextUtils;
import java.lang.annotation.Retention;
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 04ec4b6..aff1391 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Describes the cause of a disconnected call. Those disconnect causes can be converted into a more
diff --git a/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java b/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java
index 92a674c..1c31368 100644
--- a/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java
+++ b/telephony/java/android/telephony/JapanesePhoneNumberFormatter.java
@@ -16,7 +16,7 @@
package android.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.text.Editable;
/*
diff --git a/telephony/java/android/telephony/NeighboringCellInfo.java b/telephony/java/android/telephony/NeighboringCellInfo.java
index 023ed30..5f46799 100644
--- a/telephony/java/android/telephony/NeighboringCellInfo.java
+++ b/telephony/java/android/telephony/NeighboringCellInfo.java
@@ -24,7 +24,7 @@
import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index fc717e7..cbd5ed6 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -46,13 +46,17 @@
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "DOMAIN_", value = {DOMAIN_CS, DOMAIN_PS})
+ @IntDef(prefix = "DOMAIN_", value = {DOMAIN_UNKNOWN, DOMAIN_CS, DOMAIN_PS, DOMAIN_CS_PS})
public @interface Domain {}
+ /** Unknown / Unspecified domain */
+ public static final int DOMAIN_UNKNOWN = 0;
/** Circuit switching domain */
- public static final int DOMAIN_CS = 1;
+ public static final int DOMAIN_CS = android.hardware.radio.V1_5.Domain.CS;
/** Packet switching domain */
- public static final int DOMAIN_PS = 2;
+ public static final int DOMAIN_PS = android.hardware.radio.V1_5.Domain.PS;
+ /** Applicable to both CS and PS Domain */
+ public static final int DOMAIN_CS_PS = DOMAIN_CS | DOMAIN_PS;
/**
* Network registration state
@@ -504,11 +508,21 @@
}
}
+ /** @hide */
+ static @NonNull String domainToString(@Domain int domain) {
+ switch (domain) {
+ case DOMAIN_CS: return "CS";
+ case DOMAIN_PS: return "PS";
+ case DOMAIN_CS_PS: return "CS_PS";
+ default: return "UNKNOWN";
+ }
+ }
+
@NonNull
@Override
public String toString() {
return new StringBuilder("NetworkRegistrationInfo{")
- .append(" domain=").append((mDomain == DOMAIN_CS) ? "CS" : "PS")
+ .append(" domain=").append(domainToString(mDomain))
.append(" transportType=").append(
AccessNetworkConstants.transportTypeToString(mTransportType))
.append(" registrationState=").append(registrationStateToString(mRegistrationState))
@@ -646,7 +660,7 @@
* .build();
* </code></pre>
*/
- public static final class Builder{
+ public static final class Builder {
@Domain
private int mDomain;
diff --git a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
index ac6bcaa..d4ed860 100644
--- a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
+++ b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
@@ -16,15 +16,14 @@
package android.telephony;
-import com.android.i18n.phonenumbers.AsYouTypeFormatter;
-import com.android.i18n.phonenumbers.PhoneNumberUtil;
-
-import android.annotation.UnsupportedAppUsage;
-import android.telephony.PhoneNumberUtils;
+import android.compat.annotation.UnsupportedAppUsage;
import android.text.Editable;
import android.text.Selection;
import android.text.TextWatcher;
+import com.android.i18n.phonenumbers.AsYouTypeFormatter;
+import com.android.i18n.phonenumbers.PhoneNumberUtil;
+
import java.util.Locale;
/**
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 67afa7d..6e86a42 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -21,7 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java
index bfa6326..98eeacf 100644
--- a/telephony/java/android/telephony/PreciseCallState.java
+++ b/telephony/java/android/telephony/PreciseCallState.java
@@ -19,14 +19,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.DisconnectCauses;
import android.telephony.Annotation.PreciseCallStates;
import android.telephony.Annotation.PreciseDisconnectCauses;
-import android.telephony.DisconnectCause;
-import android.telephony.PreciseDisconnectCause;
import java.util.Objects;
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 0610796..31434c1 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.LinkProperties;
import android.os.Build;
import android.os.Parcel;
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index 28f6515..bc84738 100644
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -16,9 +16,7 @@
package android.telephony;
-import android.annotation.UnsupportedAppUsage;
-import android.hardware.radio.V1_0.RadioTechnology;
-import android.hardware.radio.V1_4.CellInfo.Info;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 599cd9f..8139330c 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -21,7 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
@@ -1886,7 +1886,7 @@
synchronized (mNetworkRegistrationInfos) {
for (NetworkRegistrationInfo networkRegistrationInfo : mNetworkRegistrationInfos) {
- if (networkRegistrationInfo.getDomain() == domain) {
+ if ((networkRegistrationInfo.getDomain() & domain) != 0) {
list.add(new NetworkRegistrationInfo(networkRegistrationInfo));
}
}
@@ -1902,7 +1902,6 @@
* @param transportType The transport type
* @return The matching {@link NetworkRegistrationInfo}
* @hide
- *
*/
@Nullable
@SystemApi
@@ -1911,7 +1910,7 @@
synchronized (mNetworkRegistrationInfos) {
for (NetworkRegistrationInfo networkRegistrationInfo : mNetworkRegistrationInfos) {
if (networkRegistrationInfo.getTransportType() == transportType
- && networkRegistrationInfo.getDomain() == domain) {
+ && (networkRegistrationInfo.getDomain() & domain) != 0) {
return new NetworkRegistrationInfo(networkRegistrationInfo);
}
}
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 3718bc7..3350a33 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java
index 045d1eb..3c67094 100644
--- a/telephony/java/android/telephony/SmsCbMessage.java
+++ b/telephony/java/android/telephony/SmsCbMessage.java
@@ -557,7 +557,7 @@
public ContentValues getContentValues() {
ContentValues cv = new ContentValues(16);
cv.put(CellBroadcasts.SLOT_INDEX, mSlotIndex);
- cv.put(CellBroadcasts.SUB_ID, mSubId);
+ cv.put(CellBroadcasts.SUBSCRIPTION_ID, mSubId);
cv.put(CellBroadcasts.GEOGRAPHICAL_SCOPE, mGeographicalScope);
if (mLocation.getPlmn() != null) {
cv.put(CellBroadcasts.PLMN, mLocation.getPlmn());
@@ -621,7 +621,7 @@
int format = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_FORMAT));
int priority = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_PRIORITY));
int slotIndex = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SLOT_INDEX));
- int subId = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SUB_ID));
+ int subId = cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SUBSCRIPTION_ID));
String plmn;
int plmnColumn = cursor.getColumnIndex(CellBroadcasts.PLMN);
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 3e576dc..fbe355e 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -25,9 +25,9 @@
import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.CursorWindow;
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index 2897358..c0bc29d 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -20,7 +20,7 @@
import android.annotation.Nullable;
import android.annotation.StringDef;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.os.Binder;
import android.text.TextUtils;
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 94085e9..2c0a1c9 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -18,7 +18,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index a44128c..4c8a81b 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -33,9 +33,9 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 209d6fd..df8c26d 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -36,13 +36,13 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
import android.app.ActivityThread;
import android.app.PendingIntent;
import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
diff --git a/telephony/java/android/telephony/VoLteServiceState.java b/telephony/java/android/telephony/VoLteServiceState.java
index f65c7b0..414b999 100644
--- a/telephony/java/android/telephony/VoLteServiceState.java
+++ b/telephony/java/android/telephony/VoLteServiceState.java
@@ -16,12 +16,11 @@
package android.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
/**
* Contains LTE network state related information.
diff --git a/telephony/java/android/telephony/cdma/CdmaCellLocation.java b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
index 45b1e47..9bc39a0 100644
--- a/telephony/java/android/telephony/cdma/CdmaCellLocation.java
+++ b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
@@ -16,7 +16,7 @@
package android.telephony.cdma;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.telephony.CellLocation;
diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.java b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
index cb27f64..23d46ba 100644
--- a/telephony/java/android/telephony/euicc/DownloadableSubscription.java
+++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
@@ -17,17 +17,18 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.UiccAccessRule;
+
+import com.android.internal.util.Preconditions;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import com.android.internal.util.Preconditions;
-
/**
* Information about a subscription which is downloadable to an eUICC using
* {@link EuiccManager#downloadSubscription(DownloadableSubscription, boolean, PendingIntent).
diff --git a/telephony/java/android/telephony/euicc/EuiccInfo.java b/telephony/java/android/telephony/euicc/EuiccInfo.java
index 91ebb6c..467d268 100644
--- a/telephony/java/android/telephony/euicc/EuiccInfo.java
+++ b/telephony/java/android/telephony/euicc/EuiccInfo.java
@@ -16,7 +16,7 @@
package android.telephony.euicc;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/gsm/GsmCellLocation.java b/telephony/java/android/telephony/gsm/GsmCellLocation.java
index d6780ce..30cea0e 100644
--- a/telephony/java/android/telephony/gsm/GsmCellLocation.java
+++ b/telephony/java/android/telephony/gsm/GsmCellLocation.java
@@ -16,7 +16,7 @@
package android.telephony.gsm;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.telephony.CellLocation;
diff --git a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
index 9f09d7a..d53a2e6 100644
--- a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
+++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 87e5391..998b39d 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index f4b2cef..0d6b31d 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
index 77bd984..9cce95f 100644
--- a/telephony/java/android/telephony/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -21,7 +21,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
index b7ab0a0..b70fd64 100644
--- a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
index 270e693..569c6d5 100644
--- a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
+++ b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
@@ -18,7 +18,7 @@
import android.annotation.SystemApi;
import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
diff --git a/telephony/java/android/telephony/ims/compat/ImsService.java b/telephony/java/android/telephony/ims/compat/ImsService.java
index 97a8517..eafbb14 100644
--- a/telephony/java/android/telephony/ims/compat/ImsService.java
+++ b/telephony/java/android/telephony/ims/compat/ImsService.java
@@ -17,8 +17,8 @@
package android.telephony.ims.compat;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
import android.app.Service;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
diff --git a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
index de4f174..5a9e8e2 100644
--- a/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/ImsFeature.java
@@ -17,7 +17,7 @@
package android.telephony.ims.compat.feature;
import android.annotation.IntDef;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.IInterface;
import android.os.RemoteException;
diff --git a/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
index 3fd356a..b52c371 100644
--- a/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
+++ b/telephony/java/android/telephony/ims/compat/feature/MMTelFeature.java
@@ -16,8 +16,8 @@
package android.telephony.ims.compat.feature;
-import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Message;
import android.os.RemoteException;
import android.telephony.ims.ImsCallProfile;
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
index d77f78e..acab738 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
@@ -16,7 +16,7 @@
package android.telephony.ims.compat.stub;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Message;
import android.os.RemoteException;
import android.telephony.CallQuality;
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
index e55c3d0..aae6f92 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
@@ -16,7 +16,7 @@
package android.telephony.ims.compat.stub;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
import android.os.RemoteException;
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
index e2024742..ce291d4 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
@@ -16,7 +16,7 @@
package android.telephony.ims.compat.stub;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.ims.ImsCallForwardInfo;
diff --git a/telephony/java/com/android/ims/ImsUtInterface.java b/telephony/java/com/android/ims/ImsUtInterface.java
index e80087d..50b63bd 100644
--- a/telephony/java/com/android/ims/ImsUtInterface.java
+++ b/telephony/java/com/android/ims/ImsUtInterface.java
@@ -16,13 +16,12 @@
package com.android.ims;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.Message;
import android.telephony.ims.ImsCallForwardInfo;
import android.telephony.ims.ImsSsInfo;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
/**
* Provides APIs for the supplementary service settings using IMS (Ut interface).
* It is created from 3GPP TS 24.623 (XCAP(XML Configuration Access Protocol)
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 9e786ce..1449a62 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -15,9 +15,9 @@
*/
package com.android.internal.telephony;
-import com.android.internal.util.Protocol;
+import android.compat.annotation.UnsupportedAppUsage;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import com.android.internal.util.Protocol;
/**
* @hide
diff --git a/telephony/java/com/android/internal/telephony/IccCardConstants.java b/telephony/java/com/android/internal/telephony/IccCardConstants.java
index 25f03c2..94dfae8 100644
--- a/telephony/java/com/android/internal/telephony/IccCardConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccCardConstants.java
@@ -15,11 +15,10 @@
*/
package com.android.internal.telephony;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.telephony.TelephonyManager;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
/**
* {@hide}
*/
diff --git a/telephony/java/com/android/internal/telephony/OperatorInfo.java b/telephony/java/com/android/internal/telephony/OperatorInfo.java
index 59c39b1..64d7863 100644
--- a/telephony/java/com/android/internal/telephony/OperatorInfo.java
+++ b/telephony/java/com/android/internal/telephony/OperatorInfo.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index fadb573..51701eb 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -15,7 +15,7 @@
*/
package com.android.internal.telephony;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* @hide
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 9cbcd7f..284544b 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -16,10 +16,9 @@
package com.android.internal.telephony;
+import android.compat.annotation.UnsupportedAppUsage;
import android.sysprop.TelephonyProperties;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.util.Optional;
/**
@@ -555,4 +554,5 @@
int RIL_UNSOL_PHYSICAL_CHANNEL_CONFIG = 1101;
int RIL_UNSOL_EMERGENCY_NUMBER_LIST = 1102;
int RIL_UNSOL_UICC_APPLICATIONS_ENABLEMENT_CHANGED = 1103;
+ int RIL_UNSOL_REGISTRATION_FAILED = 1104;
}
diff --git a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
index d672642..1d6ec2d 100644
--- a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
+++ b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.telephony.Rlog;
@@ -25,8 +26,6 @@
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.telephony.util.XmlUtils;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
public class Sms7BitEncodingTranslator {
private static final String TAG = "Sms7BitEncodingTranslator";
@UnsupportedAppUsage
diff --git a/telephony/java/com/android/internal/telephony/SmsAddress.java b/telephony/java/com/android/internal/telephony/SmsAddress.java
index 2a8de8c..f18256a 100644
--- a/telephony/java/com/android/internal/telephony/SmsAddress.java
+++ b/telephony/java/com/android/internal/telephony/SmsAddress.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
public abstract class SmsAddress {
// From TS 23.040 9.1.2.5 and TS 24.008 table 10.5.118
diff --git a/telephony/java/com/android/internal/telephony/SmsHeader.java b/telephony/java/com/android/internal/telephony/SmsHeader.java
index dd77b01..ab3fdf4 100644
--- a/telephony/java/com/android/internal/telephony/SmsHeader.java
+++ b/telephony/java/com/android/internal/telephony/SmsHeader.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import com.android.internal.util.HexDump;
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index d6632f3..084882b 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.telephony.SmsMessage;
import android.text.TextUtils;
diff --git a/telephony/java/com/android/internal/telephony/SmsRawData.java b/telephony/java/com/android/internal/telephony/SmsRawData.java
index 18727f3..9776c8f 100644
--- a/telephony/java/com/android/internal/telephony/SmsRawData.java
+++ b/telephony/java/com/android/internal/telephony/SmsRawData.java
@@ -17,7 +17,7 @@
package com.android.internal.telephony;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 4e42c20..ff70f8b 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony;
-import dalvik.annotation.compat.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Contains a list of string constants used to get or set telephone properties
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 1f7715b..e75c593 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.cdma;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.sysprop.TelephonyProperties;
import android.telephony.PhoneNumberUtils;
@@ -41,8 +42,6 @@
import com.android.internal.util.BitwiseInputStream;
import com.android.internal.util.HexDump;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
diff --git a/telephony/java/com/android/internal/telephony/cdma/UserData.java b/telephony/java/com/android/internal/telephony/cdma/UserData.java
index 7187ae4..524cb0c 100644
--- a/telephony/java/com/android/internal/telephony/cdma/UserData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/UserData.java
@@ -16,13 +16,12 @@
package com.android.internal.telephony.cdma.sms;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.SparseIntArray;
import com.android.internal.telephony.SmsHeader;
import com.android.internal.util.HexDump;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
public class UserData {
/**
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index d9be548..b5af646 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.cdma.sms;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.telephony.Rlog;
import android.telephony.SmsCbCmasInfo;
@@ -31,8 +32,6 @@
import com.android.internal.util.BitwiseInputStream;
import com.android.internal.util.BitwiseOutputStream;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
index a82b975..6f0de34 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
@@ -16,7 +16,7 @@
package com.android.internal.telephony.cdma.sms;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.util.SparseBooleanArray;
import com.android.internal.annotations.VisibleForTesting;
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
index c924ab3..9e2d29c 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
@@ -16,8 +16,7 @@
package com.android.internal.telephony.cdma.sms;
-
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.telephony.cdma.CdmaSmsCbProgramData;
public final class SmsEnvelope {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
index 17f69b3..5409c09 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
@@ -16,13 +16,12 @@
package com.android.internal.telephony.gsm;
+import android.compat.annotation.UnsupportedAppUsage;
import android.telephony.PhoneNumberUtils;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.SmsAddress;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.text.ParseException;
public class GsmSmsAddress extends SmsAddress {
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
index 216f616..d190345 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsCbHeader.java
@@ -16,13 +16,12 @@
package com.android.internal.telephony.gsm;
+import android.compat.annotation.UnsupportedAppUsage;
import android.telephony.SmsCbCmasInfo;
import android.telephony.SmsCbEtwsInfo;
import com.android.internal.telephony.SmsConstants;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.util.Arrays;
import java.util.Locale;
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index da32c8c..0681dc1 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -25,6 +25,7 @@
import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_SEPTETS;
import static com.android.internal.telephony.SmsConstants.MessageClass;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.telephony.PhoneNumberUtils;
import android.telephony.Rlog;
@@ -38,8 +39,6 @@
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.uicc.IccUtils;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
index f2d4624..eed9a86 100644
--- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.uicc;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.graphics.Bitmap;
@@ -25,8 +26,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.GsmAlphabet;
-import dalvik.annotation.compat.UnsupportedAppUsage;
-
import java.io.UnsupportedEncodingException;
import java.util.List;
diff --git a/test-base/hiddenapi/Android.bp b/test-base/hiddenapi/Android.bp
index c4e0fab..c202467 100644
--- a/test-base/hiddenapi/Android.bp
+++ b/test-base/hiddenapi/Android.bp
@@ -25,5 +25,8 @@
srcs: ["src/**/*.java"],
- libs: ["android.test.base"],
+ libs: [
+ "android.test.base",
+ "unsupportedappusage",
+ ],
}
diff --git a/test-base/hiddenapi/src/android/test/AndroidTestCase.java b/test-base/hiddenapi/src/android/test/AndroidTestCase.java
index 2b9beb1..fcb8d43 100644
--- a/test-base/hiddenapi/src/android/test/AndroidTestCase.java
+++ b/test-base/hiddenapi/src/android/test/AndroidTestCase.java
@@ -16,7 +16,7 @@
package android.test;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import junit.framework.TestCase;
diff --git a/test-base/hiddenapi/src/android/test/InstrumentationTestCase.java b/test-base/hiddenapi/src/android/test/InstrumentationTestCase.java
index 139cd18..a48a56c 100644
--- a/test-base/hiddenapi/src/android/test/InstrumentationTestCase.java
+++ b/test-base/hiddenapi/src/android/test/InstrumentationTestCase.java
@@ -16,7 +16,7 @@
package android.test;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import junit.framework.TestCase;
diff --git a/test-base/hiddenapi/src/junit/framework/TestCase.java b/test-base/hiddenapi/src/junit/framework/TestCase.java
index 5a54861..59fbe2b 100644
--- a/test-base/hiddenapi/src/junit/framework/TestCase.java
+++ b/test-base/hiddenapi/src/junit/framework/TestCase.java
@@ -16,7 +16,7 @@
package junit.framework;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* Stub only
diff --git a/test-base/hiddenapi/src/junit/framework/TestSuite.java b/test-base/hiddenapi/src/junit/framework/TestSuite.java
index 368c661..32305c9 100644
--- a/test-base/hiddenapi/src/junit/framework/TestSuite.java
+++ b/test-base/hiddenapi/src/junit/framework/TestSuite.java
@@ -16,7 +16,7 @@
package junit.framework;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import java.lang.reflect.Method;
diff --git a/tests/TelephonyCommonTests/Android.bp b/tests/TelephonyCommonTests/Android.bp
index 16189c8..4f7569d 100644
--- a/tests/TelephonyCommonTests/Android.bp
+++ b/tests/TelephonyCommonTests/Android.bp
@@ -38,11 +38,12 @@
// Uncomment this and comment out the jarjar rule if you want to attach a debugger and step
// through the renamed classes.
- //platform_apis: true,
+ // platform_apis: true,
libs: [
"android.test.runner",
"android.test.mock",
"android.test.base",
+ "unsupportedappusage",
],
}
diff --git a/tests/TelephonyCommonTests/jarjar-rules.txt b/tests/TelephonyCommonTests/jarjar-rules.txt
index fe34719..4d1115f 100644
--- a/tests/TelephonyCommonTests/jarjar-rules.txt
+++ b/tests/TelephonyCommonTests/jarjar-rules.txt
@@ -1 +1,3 @@
rule com.android.internal.telephony.SmsApplication* com.android.internal.telephony.tests.SmsApplication@1
+rule android.telephony.PackageChangeReceiver* com.android.internal.telephony.tests.PackageChangeReceiver@1
+rule com.android.internal.os.BackgroundThread* com.android.internal.telephony.tests.BackgroundThread@1
diff --git a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
index 6d0ee18..83fd208 100644
--- a/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
+++ b/tests/TelephonyCommonTests/src/com/android/internal/telephony/tests/SmsApplicationTest.java
@@ -17,26 +17,34 @@
package com.android.internal.telephony.tests;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNotNull;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.Manifest;
import android.app.AppOpsManager;
import android.app.role.RoleManager;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.net.Uri;
+import android.os.Handler;
import android.os.UserHandle;
import android.provider.Telephony;
import android.telephony.TelephonyManager;
@@ -48,11 +56,15 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
/**
* Unit tests for the {@link SmsApplication} utility class
@@ -80,6 +92,13 @@
AppOpsManager.OPSTR_READ_CELL_BROADCASTS
};
+ private static final Set<String> SCHEMES_FOR_PREFERRED_APP = Arrays.stream(new String[]{
+ "mms",
+ "mmsto",
+ "sms",
+ "smsto"
+ }).collect(Collectors.toSet());
+
@Mock private Context mContext;
@Mock private TelephonyManager mTelephonyManager;
@Mock private RoleManager mRoleManager;
@@ -94,13 +113,16 @@
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getSystemService(RoleManager.class)).thenReturn(mRoleManager);
when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOpsManager);
+ when(mContext.createContextAsUser(isNotNull(), anyInt())).thenReturn(mContext);
doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
.when(mPackageManager)
- .queryBroadcastReceiversAsUser(nullable(Intent.class), anyInt(), anyInt());
+ .queryBroadcastReceiversAsUser(nullable(Intent.class), anyInt(),
+ nullable(UserHandle.class));
doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
.when(mPackageManager)
- .queryIntentActivitiesAsUser(nullable(Intent.class), anyInt(), anyInt());
+ .queryIntentActivitiesAsUser(nullable(Intent.class), anyInt(),
+ nullable(UserHandle.class));
doAnswer(invocation -> getResolveInfosForIntent(invocation.getArgument(0)))
.when(mPackageManager)
.queryIntentServicesAsUser(nullable(Intent.class), anyInt(),
@@ -137,6 +159,37 @@
AppOpsManager.MODE_ALLOWED);
}
+ @Test
+ public void testPackageChanged() throws Exception {
+ setupPackageInfosForCoreApps();
+ SmsApplication.initSmsPackageMonitor(mContext);
+ verify(mContext).createContextAsUser(eq(UserHandle.ALL), anyInt());
+ ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mContext).registerReceiver(captor.capture(), isNotNull(),
+ isNull(), nullable(Handler.class));
+ BroadcastReceiver smsPackageMonitor = captor.getValue();
+
+ Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
+ packageChangedIntent.setData(
+ Uri.fromParts("package", TEST_COMPONENT_NAME.getPackageName(), null));
+ smsPackageMonitor.onReceive(mContext, packageChangedIntent);
+
+ ArgumentCaptor<IntentFilter> intentFilterCaptor =
+ ArgumentCaptor.forClass(IntentFilter.class);
+ verify(mPackageManager, times(SCHEMES_FOR_PREFERRED_APP.size()))
+ .replacePreferredActivity(intentFilterCaptor.capture(),
+ eq(IntentFilter.MATCH_CATEGORY_SCHEME
+ | IntentFilter.MATCH_ADJUSTMENT_NORMAL),
+ isNotNull(List.class),
+ eq(new ComponentName(TEST_COMPONENT_NAME.getPackageName(), SEND_TO_NAME)));
+
+ Set<String> capturedSchemes = intentFilterCaptor.getAllValues().stream()
+ .map(intentFilter -> intentFilter.getDataScheme(0))
+ .collect(Collectors.toSet());
+ assertEquals(SCHEMES_FOR_PREFERRED_APP.size(), capturedSchemes.size());
+ assertTrue(SCHEMES_FOR_PREFERRED_APP.containsAll(capturedSchemes));
+ }
+
private void setupPackageInfosForCoreApps() throws Exception {
PackageInfo phonePackageInfo = new PackageInfo();
ApplicationInfo phoneApplicationInfo = new ApplicationInfo();
diff --git a/tests/net/TEST_MAPPING b/tests/net/TEST_MAPPING
new file mode 100644
index 0000000..a7853b6
--- /dev/null
+++ b/tests/net/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "postsubmit": [
+ {
+ "name": "FrameworksNetIntegrationTests"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/net/integration/Android.bp b/tests/net/integration/Android.bp
index 7d9b7b7..874bd4b 100644
--- a/tests/net/integration/Android.bp
+++ b/tests/net/integration/Android.bp
@@ -36,6 +36,7 @@
"services.net",
"testables",
],
+ test_suites: ["device-tests"],
use_embedded_native_libs: true,
jni_libs: [
// For mockito extended
diff --git a/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java b/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java
index c50229a..d1d6a26 100644
--- a/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java
+++ b/tests/permission/src/com/android/framework/permission/tests/VibratorServicePermissionTest.java
@@ -16,12 +16,12 @@
package com.android.framework.permission.tests;
-import android.media.AudioAttributes;
import android.os.Binder;
import android.os.IVibratorService;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.test.suitebuilder.annotation.SmallTest;
@@ -52,8 +52,8 @@
try {
final VibrationEffect effect =
VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE);
- final AudioAttributes attrs = new AudioAttributes.Builder()
- .setUsage(AudioAttributes.USAGE_ALARM)
+ final VibrationAttributes attrs = new VibrationAttributes.Builder()
+ .setUsage(VibrationAttributes.USAGE_ALARM)
.build();
mVibratorService.vibrate(Process.myUid(), null, effect, attrs,
"testVibrate", new Binder());
diff --git a/wifi/Android.bp b/wifi/Android.bp
index 35a892a..3934af1 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -57,6 +57,7 @@
libs: [
// TODO(b/140299412) should be framework-system-stubs once we fix all @hide dependencies
"framework-minus-apex",
+ "unsupportedappusage",
],
srcs: [
":framework-wifi-updatable-sources",
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 61b5aef..c6aca07 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index e9f7a46..a379c75 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -20,7 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.PackageManager;
import android.net.IpConfiguration;
import android.net.IpConfiguration.ProxySettings;
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 7a59a4f..148e8a4 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index f728491..62337cb 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -19,7 +19,7 @@
import android.annotation.IntRange;
import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.NetworkInfo.DetailedState;
import android.net.shared.Inet4AddressUtils;
import android.os.Build;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 7693f9a..378c67b 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -29,8 +29,8 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.net.ConnectivityManager;
diff --git a/wifi/java/android/net/wifi/WifiSsid.java b/wifi/java/android/net/wifi/WifiSsid.java
index 90756d8..704ae81 100644
--- a/wifi/java/android/net/wifi/WifiSsid.java
+++ b/wifi/java/android/net/wifi/WifiSsid.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index c9bca4f..8fa9c3d 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.MacAddress;
import android.net.wifi.WpsInfo;
import android.os.Parcel;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
index 98ec208..710175f 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
index acf06fb..ededf67 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDeviceList.java
@@ -16,10 +16,9 @@
package android.net.wifi.p2p;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Parcelable;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
-import android.net.wifi.p2p.WifiP2pDevice;
+import android.os.Parcelable;
import android.text.TextUtils;
import java.util.ArrayList;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
index d8c50f2..21f6704 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java
@@ -17,7 +17,7 @@
package android.net.wifi.p2p;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
index 10fd09a..cdb2806 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.java
@@ -17,7 +17,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.LruCache;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 6120e4e..3459c94 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -24,7 +24,7 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.NetworkInfo;
import android.net.wifi.WpsInfo;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pProvDiscEvent.java b/wifi/java/android/net/wifi/p2p/WifiP2pProvDiscEvent.java
index 153e03c..d0fe92d 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pProvDiscEvent.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pProvDiscEvent.java
@@ -16,7 +16,7 @@
package android.net.wifi.p2p;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
/**
* A class representing a Wi-Fi p2p provisional discovery request/response
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
index 48b0703..a411502 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
@@ -19,7 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
index e32c8e8..0de7ba6 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
@@ -16,7 +16,7 @@
package android.net.wifi.p2p.nsd;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.nsd.DnsSdTxtRecord;
import android.os.Build;
import android.text.TextUtils;
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
index db0bdb8..37b442b 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceInfo.java
@@ -16,7 +16,7 @@
package android.net.wifi.p2p.nsd;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
index 87528c4..68cbb88 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceRequest.java
@@ -16,7 +16,7 @@
package android.net.wifi.p2p.nsd;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Build;
import android.os.Parcel;