summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt19
-rw-r--r--api/removed.txt1
-rw-r--r--api/system-current.txt4
-rw-r--r--api/test-current.txt1
-rw-r--r--core/java/android/app/Notification.java128
-rw-r--r--core/java/android/os/IUserManager.aidl2
-rw-r--r--core/java/android/os/PowerManager.java54
-rw-r--r--core/java/android/os/UserManager.java18
-rw-r--r--core/java/android/provider/Settings.java1
-rw-r--r--core/java/android/provider/VoicemailContract.java22
-rw-r--r--core/java/com/android/internal/app/UnlaunchableAppActivity.java2
-rw-r--r--core/jni/android/graphics/ImageDecoder.cpp2
-rw-r--r--core/jni/android_view_SurfaceControl.cpp1
-rw-r--r--core/res/res/values/attrs.xml20
-rw-r--r--core/tests/coretests/src/android/app/NotificationTest.java52
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanReadback.h44
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp8
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerUI.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java6
-rw-r--r--services/core/java/com/android/server/BatteryService.java2
-rw-r--r--services/core/java/com/android/server/content/SyncJobService.java32
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java4
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java15
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java132
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceUtils.java45
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java29
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java4
-rw-r--r--services/core/java/com/android/server/power/BatterySaverPolicy.java18
-rw-r--r--services/core/java/com/android/server/power/batterysaver/BatterySaverLocationPlugin.java4
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java62
-rw-r--r--telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java27
-rw-r--r--telephony/java/android/telephony/euicc/EuiccNotification.java179
-rw-r--r--telephony/java/android/telephony/euicc/EuiccRat.java259
-rw-r--r--telephony/java/com/android/ims/ImsCallProfile.java2
-rw-r--r--tools/aapt2/cmd/Compile.cpp4
-rw-r--r--tools/apilint/apilint.py112
38 files changed, 1071 insertions, 262 deletions
diff --git a/api/current.txt b/api/current.txt
index a75bbfa0a800..af9f89e3d9ae 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5291,8 +5291,19 @@ package android.app {
method public android.os.Bundle getExtras();
method public android.graphics.drawable.Icon getIcon();
method public android.app.RemoteInput[] getRemoteInputs();
+ method public int getSemanticAction();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.Notification.Action> CREATOR;
+ field public static final int SEMANTIC_ACTION_ARCHIVE = 5; // 0x5
+ field public static final int SEMANTIC_ACTION_DELETE = 4; // 0x4
+ field public static final int SEMANTIC_ACTION_MARK_AS_READ = 2; // 0x2
+ field public static final int SEMANTIC_ACTION_MARK_AS_UNREAD = 3; // 0x3
+ field public static final int SEMANTIC_ACTION_MUTE = 6; // 0x6
+ field public static final int SEMANTIC_ACTION_NONE = 0; // 0x0
+ field public static final int SEMANTIC_ACTION_REPLY = 1; // 0x1
+ field public static final int SEMANTIC_ACTION_THUMBS_DOWN = 9; // 0x9
+ field public static final int SEMANTIC_ACTION_THUMBS_UP = 8; // 0x8
+ field public static final int SEMANTIC_ACTION_UNMUTE = 7; // 0x7
field public android.app.PendingIntent actionIntent;
field public deprecated int icon;
field public java.lang.CharSequence title;
@@ -5308,6 +5319,7 @@ package android.app {
method public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Extender);
method public android.os.Bundle getExtras();
method public android.app.Notification.Action.Builder setAllowGeneratedReplies(boolean);
+ method public android.app.Notification.Action.Builder setSemanticAction(int);
}
public static abstract interface Notification.Action.Extender {
@@ -32121,6 +32133,7 @@ package android.os {
}
public final class PowerManager {
+ method public int getLocationPowerSaveMode();
method public boolean isDeviceIdleMode();
method public boolean isIgnoringBatteryOptimizations(java.lang.String);
method public boolean isInteractive();
@@ -32134,6 +32147,10 @@ package android.os {
field public static final java.lang.String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
field public static final java.lang.String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED";
field public static final deprecated int FULL_WAKE_LOCK = 26; // 0x1a
+ field public static final int LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF = 2; // 0x2
+ field public static final int LOCATION_MODE_FOREGROUND_ONLY = 3; // 0x3
+ field public static final int LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF = 1; // 0x1
+ field public static final int LOCATION_MODE_NO_CHANGE = 0; // 0x0
field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000
field public static final int PARTIAL_WAKE_LOCK = 1; // 0x1
field public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32; // 0x20
@@ -32421,12 +32438,12 @@ package android.os {
method public boolean isUserRunningOrStopping(android.os.UserHandle);
method public boolean isUserUnlocked();
method public boolean isUserUnlocked(android.os.UserHandle);
+ method public boolean requestQuietModeEnabled(boolean, android.os.UserHandle);
method public deprecated boolean setRestrictionsChallenge(java.lang.String);
method public deprecated void setUserRestriction(java.lang.String, boolean);
method public deprecated void setUserRestrictions(android.os.Bundle);
method public deprecated void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
method public static boolean supportsMultipleUsers();
- method public boolean trySetQuietModeEnabled(boolean, android.os.UserHandle);
field public static final java.lang.String ALLOW_PARENT_PROFILE_APP_LINKING = "allow_parent_profile_app_linking";
field public static final java.lang.String DISALLOW_ADD_MANAGED_PROFILE = "no_add_managed_profile";
field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
diff --git a/api/removed.txt b/api/removed.txt
index 2aab223ed281..77088e5bdab7 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -265,6 +265,7 @@ package android.os {
method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
+ method public deprecated boolean trySetQuietModeEnabled(boolean, android.os.UserHandle);
}
}
diff --git a/api/system-current.txt b/api/system-current.txt
index fbb8335b2a79..4c95beb6778a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -191,10 +191,6 @@ package android {
field public static final int isVrOnly = 16844152; // 0x1010578
field public static final int requiredSystemPropertyName = 16844133; // 0x1010565
field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566
- field public static final int searchKeyphrase = 16843871; // 0x101045f
- field public static final int searchKeyphraseId = 16843870; // 0x101045e
- field public static final int searchKeyphraseRecognitionFlags = 16843942; // 0x10104a6
- field public static final int searchKeyphraseSupportedLocales = 16843872; // 0x1010460
}
public static final class R.raw {
diff --git a/api/test-current.txt b/api/test-current.txt
index b16e700c4768..b15ec4a07603 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -483,6 +483,7 @@ package android.provider {
}
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
+ field public static final java.lang.String LOW_POWER_MODE = "low_power";
field public static final java.lang.String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index a3836048cc7d..75dc57110c93 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1268,10 +1268,67 @@ public class Notification implements Parcelable
*/
private static final String EXTRA_DATA_ONLY_INPUTS = "android.extra.DATA_ONLY_INPUTS";
+ /**
+ * {@link }: No semantic action defined.
+ */
+ public static final int SEMANTIC_ACTION_NONE = 0;
+
+ /**
+ * {@code SemanticAction}: Reply to a conversation, chat, group, or wherever replies
+ * may be appropriate.
+ */
+ public static final int SEMANTIC_ACTION_REPLY = 1;
+
+ /**
+ * {@code SemanticAction}: Mark content as read.
+ */
+ public static final int SEMANTIC_ACTION_MARK_AS_READ = 2;
+
+ /**
+ * {@code SemanticAction}: Mark content as unread.
+ */
+ public static final int SEMANTIC_ACTION_MARK_AS_UNREAD = 3;
+
+ /**
+ * {@code SemanticAction}: Delete the content associated with the notification. This
+ * could mean deleting an email, message, etc.
+ */
+ public static final int SEMANTIC_ACTION_DELETE = 4;
+
+ /**
+ * {@code SemanticAction}: Archive the content associated with the notification. This
+ * could mean archiving an email, message, etc.
+ */
+ public static final int SEMANTIC_ACTION_ARCHIVE = 5;
+
+ /**
+ * {@code SemanticAction}: Mute the content associated with the notification. This could
+ * mean silencing a conversation or currently playing media.
+ */
+ public static final int SEMANTIC_ACTION_MUTE = 6;
+
+ /**
+ * {@code SemanticAction}: Unmute the content associated with the notification. This could
+ * mean un-silencing a conversation or currently playing media.
+ */
+ public static final int SEMANTIC_ACTION_UNMUTE = 7;
+
+ /**
+ * {@code SemanticAction}: Mark content with a thumbs up.
+ */
+ public static final int SEMANTIC_ACTION_THUMBS_UP = 8;
+
+ /**
+ * {@code SemanticAction}: Mark content with a thumbs down.
+ */
+ public static final int SEMANTIC_ACTION_THUMBS_DOWN = 9;
+
+
private final Bundle mExtras;
private Icon mIcon;
private final RemoteInput[] mRemoteInputs;
private boolean mAllowGeneratedReplies = true;
+ private final @SemanticAction int mSemanticAction;
/**
* Small icon representing the action.
@@ -1306,6 +1363,7 @@ public class Notification implements Parcelable
mExtras = Bundle.setDefusable(in.readBundle(), true);
mRemoteInputs = in.createTypedArray(RemoteInput.CREATOR);
mAllowGeneratedReplies = in.readInt() == 1;
+ mSemanticAction = in.readInt();
}
/**
@@ -1313,12 +1371,14 @@ public class Notification implements Parcelable
*/
@Deprecated
public Action(int icon, CharSequence title, PendingIntent intent) {
- this(Icon.createWithResource("", icon), title, intent, new Bundle(), null, true);
+ this(Icon.createWithResource("", icon), title, intent, new Bundle(), null, true,
+ SEMANTIC_ACTION_NONE);
}
/** Keep in sync with {@link Notification.Action.Builder#Builder(Action)}! */
private Action(Icon icon, CharSequence title, PendingIntent intent, Bundle extras,
- RemoteInput[] remoteInputs, boolean allowGeneratedReplies) {
+ RemoteInput[] remoteInputs, boolean allowGeneratedReplies,
+ @SemanticAction int semanticAction) {
this.mIcon = icon;
if (icon != null && icon.getType() == Icon.TYPE_RESOURCE) {
this.icon = icon.getResId();
@@ -1328,6 +1388,7 @@ public class Notification implements Parcelable
this.mExtras = extras != null ? extras : new Bundle();
this.mRemoteInputs = remoteInputs;
this.mAllowGeneratedReplies = allowGeneratedReplies;
+ this.mSemanticAction = semanticAction;
}
/**
@@ -1366,6 +1427,15 @@ public class Notification implements Parcelable
}
/**
+ * Returns the {@code SemanticAction} associated with this {@link Action}. A
+ * {@code SemanticAction} denotes what an {@link Action}'s {@link PendingIntent} will do
+ * (eg. reply, mark as read, delete, etc).
+ */
+ public @SemanticAction int getSemanticAction() {
+ return mSemanticAction;
+ }
+
+ /**
* Get the list of inputs to be collected from the user that ONLY accept data when this
* action is sent. These remote inputs are guaranteed to return true on a call to
* {@link RemoteInput#isDataOnly}.
@@ -1389,6 +1459,7 @@ public class Notification implements Parcelable
private boolean mAllowGeneratedReplies = true;
private final Bundle mExtras;
private ArrayList<RemoteInput> mRemoteInputs;
+ private @SemanticAction int mSemanticAction;
/**
* Construct a new builder for {@link Action} object.
@@ -1408,7 +1479,7 @@ public class Notification implements Parcelable
* @param intent the {@link PendingIntent} to fire when users trigger this action
*/
public Builder(Icon icon, CharSequence title, PendingIntent intent) {
- this(icon, title, intent, new Bundle(), null, true);
+ this(icon, title, intent, new Bundle(), null, true, SEMANTIC_ACTION_NONE);
}
/**
@@ -1419,11 +1490,12 @@ public class Notification implements Parcelable
public Builder(Action action) {
this(action.getIcon(), action.title, action.actionIntent,
new Bundle(action.mExtras), action.getRemoteInputs(),
- action.getAllowGeneratedReplies());
+ action.getAllowGeneratedReplies(), action.getSemanticAction());
}
private Builder(Icon icon, CharSequence title, PendingIntent intent, Bundle extras,
- RemoteInput[] remoteInputs, boolean allowGeneratedReplies) {
+ RemoteInput[] remoteInputs, boolean allowGeneratedReplies,
+ @SemanticAction int semanticAction) {
mIcon = icon;
mTitle = title;
mIntent = intent;
@@ -1433,6 +1505,7 @@ public class Notification implements Parcelable
Collections.addAll(mRemoteInputs, remoteInputs);
}
mAllowGeneratedReplies = allowGeneratedReplies;
+ mSemanticAction = semanticAction;
}
/**
@@ -1488,6 +1561,19 @@ public class Notification implements Parcelable
}
/**
+ * Sets the {@code SemanticAction} for this {@link Action}. A
+ * {@code SemanticAction} denotes what an {@link Action}'s
+ * {@link PendingIntent} will do (eg. reply, mark as read, delete, etc).
+ * @param semanticAction a SemanticAction defined within {@link Action} with
+ * {@code SEMANTIC_ACTION_} prefixes
+ * @return this object for method chaining
+ */
+ public Builder setSemanticAction(@SemanticAction int semanticAction) {
+ mSemanticAction = semanticAction;
+ return this;
+ }
+
+ /**
* Apply an extender to this action builder. Extenders may be used to add
* metadata or change options on this builder.
*/
@@ -1528,7 +1614,7 @@ public class Notification implements Parcelable
RemoteInput[] textInputsArr = textInputs.isEmpty()
? null : textInputs.toArray(new RemoteInput[textInputs.size()]);
return new Action(mIcon, mTitle, mIntent, mExtras, textInputsArr,
- mAllowGeneratedReplies);
+ mAllowGeneratedReplies, mSemanticAction);
}
}
@@ -1540,12 +1626,15 @@ public class Notification implements Parcelable
actionIntent, // safe to alias
mExtras == null ? new Bundle() : new Bundle(mExtras),
getRemoteInputs(),
- getAllowGeneratedReplies());
+ getAllowGeneratedReplies(),
+ getSemanticAction());
}
+
@Override
public int describeContents() {
return 0;
}
+
@Override
public void writeToParcel(Parcel out, int flags) {
final Icon ic = getIcon();
@@ -1565,7 +1654,9 @@ public class Notification implements Parcelable
out.writeBundle(mExtras);
out.writeTypedArray(mRemoteInputs, flags);
out.writeInt(mAllowGeneratedReplies ? 1 : 0);
+ out.writeInt(mSemanticAction);
}
+
public static final Parcelable.Creator<Action> CREATOR =
new Parcelable.Creator<Action>() {
public Action createFromParcel(Parcel in) {
@@ -1827,6 +1918,29 @@ public class Notification implements Parcelable
return (mFlags & FLAG_HINT_DISPLAY_INLINE) != 0;
}
}
+
+ /**
+ * Provides meaning to an {@link Action} that hints at what the associated
+ * {@link PendingIntent} will do. For example, an {@link Action} with a
+ * {@link PendingIntent} that replies to a text message notification may have the
+ * {@link #SEMANTIC_ACTION_REPLY} {@code SemanticAction} set within it.
+ *
+ * @hide
+ */
+ @IntDef(prefix = { "SEMANTIC_ACTION_" }, value = {
+ SEMANTIC_ACTION_NONE,
+ SEMANTIC_ACTION_REPLY,
+ SEMANTIC_ACTION_MARK_AS_READ,
+ SEMANTIC_ACTION_MARK_AS_UNREAD,
+ SEMANTIC_ACTION_DELETE,
+ SEMANTIC_ACTION_ARCHIVE,
+ SEMANTIC_ACTION_MUTE,
+ SEMANTIC_ACTION_UNMUTE,
+ SEMANTIC_ACTION_THUMBS_UP,
+ SEMANTIC_ACTION_THUMBS_DOWN
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SemanticAction {}
}
/**
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 01d6b022043f..65e9473380ce 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -97,7 +97,7 @@ interface IUserManager {
boolean isUserRunning(int userId);
boolean isUserNameSet(int userHandle);
boolean hasRestrictedProfiles();
- boolean trySetQuietModeEnabled(String callingPackage, boolean enableQuietMode, int userHandle, in IntentSender target);
+ boolean requestQuietModeEnabled(String callingPackage, boolean enableQuietMode, int userHandle, in IntentSender target);
long getUserStartRealtime();
long getUserUnlockRealtime();
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index cd6d41b3f43c..3798a5ec15b5 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -565,6 +565,42 @@ public final class PowerManager {
int OPTIONAL_SENSORS = 13;
}
+ /**
+ * Either the location providers shouldn't be affected by battery saver,
+ * or battery saver is off.
+ */
+ public static final int LOCATION_MODE_NO_CHANGE = 0;
+
+ /**
+ * In this mode, the GPS based location provider should be disabled when battery saver is on and
+ * the device is non-interactive.
+ */
+ public static final int LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF = 1;
+
+ /**
+ * All location providers should be disabled when battery saver is on and
+ * the device is non-interactive.
+ */
+ public static final int LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF = 2;
+
+ /**
+ * In this mode, all the location providers will be kept available, but location fixes
+ * should only be provided to foreground apps.
+ */
+ public static final int LOCATION_MODE_FOREGROUND_ONLY = 3;
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"LOCATION_MODE_"}, value = {
+ LOCATION_MODE_NO_CHANGE,
+ LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF,
+ LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF,
+ LOCATION_MODE_FOREGROUND_ONLY,
+ })
+ public @interface LocationPowerSaveMode {}
+
final Context mContext;
final IPowerManager mService;
final Handler mHandler;
@@ -1143,6 +1179,24 @@ public final class PowerManager {
}
/**
+ * Returns how location features should behave when battery saver is on. When battery saver
+ * is off, this will always return {@link #LOCATION_MODE_NO_CHANGE}.
+ *
+ * <p>This API is normally only useful for components that provide location features.
+ *
+ * @see #isPowerSaveMode()
+ * @see #ACTION_POWER_SAVE_MODE_CHANGED
+ */
+ @LocationPowerSaveMode
+ public int getLocationPowerSaveMode() {
+ final PowerSaveState powerSaveState = getPowerSaveState(ServiceType.GPS);
+ if (!powerSaveState.globalBatterySaverEnabled) {
+ return LOCATION_MODE_NO_CHANGE;
+ }
+ return powerSaveState.gpsMode;
+ }
+
+ /**
* Returns true if the device is currently in idle mode. This happens when a device
* has been sitting unused and unmoving for a sufficiently long period of time, so that
* it decides to go into a lower power-use state. This may involve things like turning
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 4e94c321e0a5..9ececa6be2a2 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2209,6 +2209,12 @@ public class UserManager {
}
}
+ /** @removed */
+ @Deprecated
+ public boolean trySetQuietModeEnabled(boolean enableQuietMode, @NonNull UserHandle userHandle) {
+ return requestQuietModeEnabled(enableQuietMode, userHandle);
+ }
+
/**
* Enables or disables quiet mode for a managed profile. If quiet mode is enabled, apps in a
* managed profile don't run, generate notifications, or consume data or battery.
@@ -2234,22 +2240,22 @@ public class UserManager {
*
* @see #isQuietModeEnabled(UserHandle)
*/
- public boolean trySetQuietModeEnabled(boolean enableQuietMode, @NonNull UserHandle userHandle) {
- return trySetQuietModeEnabled(enableQuietMode, userHandle, null);
+ public boolean requestQuietModeEnabled(boolean enableQuietMode, @NonNull UserHandle userHandle) {
+ return requestQuietModeEnabled(enableQuietMode, userHandle, null);
}
/**
- * Similar to {@link #trySetQuietModeEnabled(boolean, UserHandle)}, except you can specify
+ * Similar to {@link #requestQuietModeEnabled(boolean, UserHandle)}, except you can specify
* a target to start when user is unlocked. If {@code target} is specified, caller must have
* the {@link android.Manifest.permission#MANAGE_USERS} permission.
*
- * @see {@link #trySetQuietModeEnabled(boolean, UserHandle)}
+ * @see {@link #requestQuietModeEnabled(boolean, UserHandle)}
* @hide
*/
- public boolean trySetQuietModeEnabled(
+ public boolean requestQuietModeEnabled(
boolean enableQuietMode, @NonNull UserHandle userHandle, IntentSender target) {
try {
- return mService.trySetQuietModeEnabled(
+ return mService.requestQuietModeEnabled(
mContext.getPackageName(), enableQuietMode, userHandle.getIdentifier(), target);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index db32144b9c45..dc9c85781873 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10058,6 +10058,7 @@ public final class Settings {
* If 1 low power mode is enabled.
* @hide
*/
+ @TestApi
public static final String LOW_POWER_MODE = "low_power";
/**
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 70de9ee49d94..c568b6fbe0c4 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -106,9 +106,12 @@ public class VoicemailContract {
/**
* Broadcast intent to inform a new visual voicemail SMS has been received. This intent will
- * only be delivered to the telephony service. {@link #EXTRA_VOICEMAIL_SMS} will be included.
- */
- /** @hide */
+ * only be delivered to the telephony service.
+ *
+ * @see #EXTRA_VOICEMAIL_SMS
+ * @see #EXTRA_TARGET_PACKAGE
+ *
+ * @hide */
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_VOICEMAIL_SMS_RECEIVED =
"com.android.internal.provider.action.VOICEMAIL_SMS_RECEIVED";
@@ -121,6 +124,19 @@ public class VoicemailContract {
public static final String EXTRA_VOICEMAIL_SMS = "android.provider.extra.VOICEMAIL_SMS";
/**
+ * Extra in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} indicating the target package to bind {@link
+ * android.telephony.VisualVoicemailService}.
+ *
+ * <p>This extra should be set to android.telephony.VisualVoicemailSmsFilterSettings#packageName
+ * while performing filtering. Since the default dialer might change between the filter sending
+ * it and telephony binding to the service, this ensures the service will not receive SMS
+ * filtered by the previous app.
+ *
+ * @hide
+ */
+ public static final String EXTRA_TARGET_PACKAGE = "android.provider.extra.TARGET_PACAKGE";
+
+ /**
* Extra included in {@link Intent#ACTION_PROVIDER_CHANGED} broadcast intents to indicate if the
* receiving package made this change.
*/
diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
index 2eadaf3a06b0..902c8c1662ea 100644
--- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java
+++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
@@ -111,7 +111,7 @@ public class UnlaunchableAppActivity extends Activity
@Override
public void onClick(DialogInterface dialog, int which) {
if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE && which == DialogInterface.BUTTON_POSITIVE) {
- UserManager.get(this).trySetQuietModeEnabled(false, UserHandle.of(mUserId), mTarget);
+ UserManager.get(this).requestQuietModeEnabled(false, UserHandle.of(mUserId), mTarget);
}
}
diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp
index ec03f82b17e0..a0a4be4590be 100644
--- a/core/jni/android/graphics/ImageDecoder.cpp
+++ b/core/jni/android/graphics/ImageDecoder.cpp
@@ -67,8 +67,8 @@ struct ImageDecoder {
kOpaque = -1,
};
- std::unique_ptr<SkAndroidCodec> mCodec;
NinePatchPeeker mPeeker;
+ std::unique_ptr<SkAndroidCodec> mCodec;
};
static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 5e5d59b8aaca..0ef5445afffc 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -72,7 +72,6 @@ static struct {
// Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref.
void DeleteScreenshot(void* addr, void* context) {
- SkASSERT(addr == ((ScreenshotClient*) context)->getPixels());
delete ((ScreenshotClient*) context);
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 79c8e04caefa..addbbf5c6ce9 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7760,21 +7760,21 @@
<attr name="settingsActivity" />
</declare-styleable>
- <!-- @SystemApi Use <code>trust-agent</code> as the root tag of the XML resource that
+ <!-- Use <code>trust-agent</code> as the root tag of the XML resource that
describes an {@link android.service.trust.TrustAgentService}, which is
referenced from its {@link android.service.trust.TrustAgentService#TRUST_AGENT_META_DATA}
meta-data entry. Described here are the attributes that can be included in that tag.
@hide -->
<declare-styleable name="TrustAgent">
- <!-- @SystemApi Component name of an activity that allows the user to modify
+ <!-- Component name of an activity that allows the user to modify
the settings for this trust agent. @hide -->
<attr name="settingsActivity" />
- <!-- @SystemApi Title for a preference that allows that user to launch the
+ <!-- Title for a preference that allows that user to launch the
activity to modify trust agent settings. @hide -->
<attr name="title" />
- <!-- @SystemApi Summary for the same preference as the title. @hide -->
+ <!-- Summary for the same preference as the title. @hide -->
<attr name="summary" />
- <!-- @SystemApi Whether trust agent can unlock a user profile @hide -->
+ <!-- Whether trust agent can unlock a user profile @hide -->
<attr name="unlockProfile" format="boolean"/>
</declare-styleable>
@@ -7984,16 +7984,16 @@
by the enrollment application.
Described here are the attributes that can be included in that tag.
@hide
- @SystemApi -->
+ -->
<declare-styleable name="VoiceEnrollmentApplication">
- <!-- A globally unique ID for the keyphrase. @hide @SystemApi -->
+ <!-- A globally unique ID for the keyphrase. @hide -->
<attr name="searchKeyphraseId" format="integer" />
- <!-- The actual keyphrase/hint text, or empty if not keyphrase dependent. @hide @SystemApi -->
+ <!-- The actual keyphrase/hint text, or empty if not keyphrase dependent. @hide -->
<attr name="searchKeyphrase" format="string" />
<!-- A comma separated list of BCP-47 language tag for locales that are supported
- for this keyphrase, or empty if not locale dependent. @hide @SystemApi -->
+ for this keyphrase, or empty if not locale dependent. @hide -->
<attr name="searchKeyphraseSupportedLocales" format="string" />
- <!-- Flags for supported recognition modes. @hide @SystemApi -->
+ <!-- Flags for supported recognition modes. @hide -->
<attr name="searchKeyphraseRecognitionFlags">
<flag name="none" value="0" />
<flag name="voiceTrigger" value="0x1" />
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index b51c677e74ff..9ab7544618ab 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -18,11 +18,13 @@ package android.app;
import static com.android.internal.util.NotificationColorUtil.satisfiesTextContrast;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
@@ -40,6 +42,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.function.Consumer;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class NotificationTest {
@@ -281,6 +285,40 @@ public class NotificationTest {
assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
}
+ @Test
+ public void action_builder_hasDefault() {
+ Notification.Action action = makeNotificationAction(null);
+ assertEquals(Notification.Action.SEMANTIC_ACTION_NONE, action.getSemanticAction());
+ }
+
+ @Test
+ public void action_builder_setSemanticAction() {
+ Notification.Action action = makeNotificationAction(
+ builder -> builder.setSemanticAction(Notification.Action.SEMANTIC_ACTION_REPLY));
+ assertEquals(Notification.Action.SEMANTIC_ACTION_REPLY, action.getSemanticAction());
+ }
+
+ @Test
+ public void action_parcel() {
+ Notification.Action action = writeAndReadParcelable(
+ makeNotificationAction(builder -> {
+ builder.setSemanticAction(Notification.Action.SEMANTIC_ACTION_ARCHIVE);
+ builder.setAllowGeneratedReplies(true);
+ }));
+
+ assertEquals(Notification.Action.SEMANTIC_ACTION_ARCHIVE, action.getSemanticAction());
+ assertTrue(action.getAllowGeneratedReplies());
+ }
+
+ @Test
+ public void action_clone() {
+ Notification.Action action = makeNotificationAction(
+ builder -> builder.setSemanticAction(Notification.Action.SEMANTIC_ACTION_DELETE));
+ assertEquals(
+ Notification.Action.SEMANTIC_ACTION_DELETE,
+ action.clone().getSemanticAction());
+ }
+
private Notification.Builder getMediaNotification() {
MediaSession session = new MediaSession(mContext, "test");
return new Notification.Builder(mContext, "color")
@@ -300,4 +338,18 @@ public class NotificationTest {
p.setDataPosition(0);
return p.readParcelable(/* classLoader */ null);
}
+
+ /**
+ * Creates a Notification.Action by mocking initial dependencies and then applying
+ * transformations if they're defined.
+ */
+ private Notification.Action makeNotificationAction(
+ @Nullable Consumer<Notification.Action.Builder> transformation) {
+ Notification.Action.Builder actionBuilder =
+ new Notification.Action.Builder(null, "Test Title", null);
+ if (transformation != null) {
+ transformation.accept(actionBuilder);
+ }
+ return actionBuilder.build();
+ }
}
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanReadback.h b/libs/hwui/pipeline/skia/SkiaVulkanReadback.h
new file mode 100644
index 000000000000..65b89d617f7b
--- /dev/null
+++ b/libs/hwui/pipeline/skia/SkiaVulkanReadback.h
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "Readback.h"
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+class SkiaVulkanReadback : public Readback {
+public:
+ SkiaVulkanReadback(renderthread::RenderThread& thread) : Readback(thread) {}
+
+ virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect,
+ SkBitmap* bitmap) override {
+ //TODO: implement Vulkan readback.
+ return CopyResult::UnknownError;
+ }
+
+ virtual CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
+ SkBitmap* bitmap) override {
+ //TODO: implement Vulkan readback.
+ return CopyResult::UnknownError;
+ }
+};
+
+} /* namespace skiapipeline */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 79dc09ffbf1d..8e0546b529af 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -24,6 +24,7 @@
#include "hwui/Bitmap.h"
#include "pipeline/skia/SkiaOpenGLPipeline.h"
#include "pipeline/skia/SkiaOpenGLReadback.h"
+#include "pipeline/skia/SkiaVulkanReadback.h"
#include "pipeline/skia/SkiaVulkanPipeline.h"
#include "renderstate/RenderState.h"
#include "renderthread/OpenGLPipeline.h"
@@ -158,12 +159,11 @@ Readback& RenderThread::readback() {
mReadback = new OpenGLReadbackImpl(*this);
break;
case RenderPipelineType::SkiaGL:
- case RenderPipelineType::SkiaVulkan:
- // It works to use the OpenGL pipeline for Vulkan but this is not
- // ideal as it causes us to create an OpenGL context in addition
- // to the Vulkan one.
mReadback = new skiapipeline::SkiaOpenGLReadback(*this);
break;
+ case RenderPipelineType::SkiaVulkan:
+ mReadback = new skiapipeline::SkiaVulkanReadback(*this);
+ break;
default:
LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
break;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index bd46c5f8ad0b..e49e80df7da9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -103,11 +103,12 @@ public class KeyguardSliceProvider extends SliceProvider implements
@Override
public Slice onBindSlice(Uri sliceUri) {
- ListBuilder builder = new ListBuilder(mSliceUri)
- .addRow(new RowBuilder(mDateUri).setTitle(mLastText));
+ ListBuilder builder = new ListBuilder(getContext(), mSliceUri);
+ builder.addRow(new RowBuilder(builder, mDateUri).setTitle(mLastText));
if (!TextUtils.isEmpty(mNextAlarm)) {
Icon icon = Icon.createWithResource(getContext(), R.drawable.ic_access_alarms_big);
- builder.addRow(new RowBuilder(mAlarmUri).setTitle(mNextAlarm).addEndItem(icon));
+ builder.addRow(new RowBuilder(builder, mAlarmUri)
+ .setTitle(mNextAlarm).addEndItem(icon));
}
return builder.build();
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index c1a36239662c..a351c09f68b7 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -131,10 +131,15 @@ public class PowerUI extends SystemUI {
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
final ContentResolver resolver = mContext.getContentResolver();
- int defWarnLevel = mContext.getResources().getInteger(
+ final int defWarnLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryWarningLevel);
- int warnLevel = Settings.Global.getInt(resolver,
+ final int lowPowerModeTriggerLevel = Settings.Global.getInt(resolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, defWarnLevel);
+
+ // NOTE: Keep the logic in sync with BatteryService.
+ // TODO: Propagate this value from BatteryService to system UI, really.
+ int warnLevel = Math.min(defWarnLevel, lowPowerModeTriggerLevel);
+
if (warnLevel == 0) {
warnLevel = defWarnLevel;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
index 7f4deb0372f5..0f8d59b12ddb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
@@ -61,7 +61,7 @@ public class ManagedProfileControllerImpl implements ManagedProfileController {
public void setWorkModeEnabled(boolean enableWorkMode) {
synchronized (mProfiles) {
for (UserInfo ui : mProfiles) {
- if (!mUserManager.trySetQuietModeEnabled(!enableWorkMode, UserHandle.of(ui.id))) {
+ if (!mUserManager.requestQuietModeEnabled(!enableWorkMode, UserHandle.of(ui.id))) {
StatusBarManager statusBarManager = (StatusBarManager) mContext
.getSystemService(android.app.Service.STATUS_BAR_SERVICE);
statusBarManager.collapsePanels();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index be28569ef629..cd409d86a3dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -33,8 +33,13 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Arrays;
+
import androidx.app.slice.SliceItem;
+import androidx.app.slice.SliceProvider;
+import androidx.app.slice.SliceSpecs;
import androidx.app.slice.core.SliceQuery;
+import androidx.app.slice.widget.SliceLiveData;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -47,6 +52,7 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
public void setup() {
mProvider = new TestableKeyguardSliceProvider();
mProvider.attachInfo(getContext(), null);
+ SliceProvider.setSpecs(Arrays.asList(SliceSpecs.LIST));
}
@Test
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index dcb0fabf0345..af0b66daad50 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -298,6 +298,8 @@ public final class BatteryService extends SystemService {
final int lowPowerModeTriggerLevel = Settings.Global.getInt(resolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, defWarnLevel);
+ // NOTE: Keep the logic in sync with PowerUI.java in systemUI.
+ // TODO: Propagate this value from BatteryService to system UI, really.
mLowBatteryWarningLevel = Math.min(defWarnLevel, lowPowerModeTriggerLevel);
if (mLowBatteryWarningLevel == 0) {
diff --git a/services/core/java/com/android/server/content/SyncJobService.java b/services/core/java/com/android/server/content/SyncJobService.java
index d957ca054819..40a93c1c2808 100644
--- a/services/core/java/com/android/server/content/SyncJobService.java
+++ b/services/core/java/com/android/server/content/SyncJobService.java
@@ -22,10 +22,12 @@ import android.content.Intent;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.SparseLongArray;
import com.android.internal.annotations.GuardedBy;
@@ -44,6 +46,9 @@ public class SyncJobService extends JobService {
@GuardedBy("mLock")
private final SparseBooleanArray mStartedSyncs = new SparseBooleanArray();
+ @GuardedBy("mLock")
+ private final SparseLongArray mJobStartUptimes = new SparseLongArray();
+
private final SyncLogger mLogger = SyncLogger.getInstance();
/**
@@ -82,7 +87,9 @@ public class SyncJobService extends JobService {
synchronized (mLock) {
final int jobId = params.getJobId();
mJobParamsMap.put(jobId, params);
+
mStartedSyncs.delete(jobId);
+ mJobStartUptimes.put(jobId, SystemClock.uptimeMillis());
}
Message m = Message.obtain();
m.what = SyncManager.SyncHandler.MESSAGE_START_SYNC;
@@ -113,14 +120,24 @@ public class SyncJobService extends JobService {
final int jobId = params.getJobId();
mJobParamsMap.remove(jobId);
- if (!mStartedSyncs.get(jobId)) {
- final String message = "Job " + jobId + " didn't start: params=" +
- jobParametersToString(params);
- mLogger.log(message);
- Slog.wtf(TAG, message);
+ final long startUptime = mJobStartUptimes.get(jobId);
+ final long nowUptime = SystemClock.uptimeMillis();
+ if (startUptime == 0) {
+ wtf("Job " + jobId + " start uptime not found: "
+ + " params=" + jobParametersToString(params));
+ } else if ((nowUptime - startUptime) > 60 * 1000) {
+ // WTF if startSyncH() hasn't happened, *unless* onStopJob() was called too soon.
+ // (1 minute threshold.)
+ if (!mStartedSyncs.get(jobId)) {
+ wtf("Job " + jobId + " didn't start: "
+ + " startUptime=" + startUptime
+ + " nowUptime=" + nowUptime
+ + " params=" + jobParametersToString(params));
+ }
}
mStartedSyncs.delete(jobId);
+ mJobStartUptimes.delete(jobId);
}
Message m = Message.obtain();
m.what = SyncManager.SyncHandler.MESSAGE_STOP_SYNC;
@@ -169,4 +186,9 @@ public class SyncJobService extends JobService {
+ SyncOperation.maybeCreateFromJobExtras(params.getExtras());
}
}
+
+ private void wtf(String message) {
+ mLogger.log(message);
+ Slog.wtf(TAG, message);
+ }
}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index e6de07d209a1..e158819cd89f 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -84,8 +84,6 @@ import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
-import com.android.server.power.BatterySaverPolicy;
-
import libcore.io.IoUtils;
import java.io.File;
@@ -579,7 +577,7 @@ public class GnssLocationProvider implements LocationProviderInterface {
final PowerSaveState result =
mPowerManager.getPowerSaveState(ServiceType.GPS);
switch (result.gpsMode) {
- case BatterySaverPolicy.GPS_MODE_DISABLED_WHEN_SCREEN_OFF:
+ case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
// If we are in battery saver mode and the screen is off, disable GPS.
disableGps |= result.batterySaverEnabled && !mPowerManager.isInteractive();
break;
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 700ccad8527a..b5d284494d20 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -822,21 +822,24 @@ public class ZenModeHelper {
@VisibleForTesting
protected void applyRestrictions() {
- final boolean zen = mZenMode != Global.ZEN_MODE_OFF;
+ final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
+ final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
// notification restrictions
final boolean muteNotifications =
(mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
// call restrictions
- final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers
+ final boolean muteCalls = zenAlarmsOnly
+ || (zenPriorityOnly && !mConfig.allowCalls && !mConfig.allowRepeatCallers)
|| (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
// alarm restrictions
- final boolean muteAlarms = zen && !mConfig.allowAlarms;
+ final boolean muteAlarms = zenPriorityOnly && !mConfig.allowAlarms;
// alarm restrictions
- final boolean muteMediaAndSystemSounds = zen && !mConfig.allowMediaSystemOther;
+ final boolean muteMediaAndSystemSounds = zenPriorityOnly && !mConfig.allowMediaSystemOther;
// total silence restrictions
- final boolean muteEverything = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
- || areAllBehaviorSoundsMuted();
+ final boolean muteEverything = zenSilence
+ || (zenPriorityOnly && areAllBehaviorSoundsMuted());
for (int usage : AudioAttributes.SDK_USAGES) {
final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f7f78b9cfcfe..57c0b4a5fe88 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2697,12 +2697,6 @@ public class PackageManagerService extends IPackageManager.Stub
mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()
|| disabledPs.pkg == null) {
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "Possibly deleted app: " + ps.dumpState_temp()
- + "; path: " + (disabledPs.codePath == null ? "<<NULL>>":disabledPs.codePath)
- + "; pkg: " + (disabledPs.pkg==null?"<<NULL>>":disabledPs.pkg.toString()));
-}
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
}
@@ -2754,10 +2748,6 @@ Slog.e("TODD",
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
mSettings.removeDisabledSystemPackageLPw(deletedAppName);
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "remove update; name: " + deletedAppName + ", exists? " + (deletedPkg != null));
-}
final String msg;
if (deletedPkg == null) {
// should have found an update, but, we didn't; remove everything
@@ -8193,12 +8183,12 @@ Slog.e("TODD",
}
private void collectCertificatesLI(PackageSetting ps, PackageParser.Package pkg,
- final @ParseFlags int parseFlags) throws PackageManagerException {
+ final @ParseFlags int parseFlags, boolean forceCollect) throws PackageManagerException {
// When upgrading from pre-N MR1, verify the package time stamp using the package
// directory and not the APK file.
final long lastModifiedTime = mIsPreNMR1Upgrade
? new File(pkg.codePath).lastModified() : getLastModifiedTime(pkg);
- if (ps != null
+ if (ps != null && !forceCollect
&& ps.codePathString.equals(pkg.codePath)
&& ps.timeStamp == lastModifiedTime
&& !isCompatSignatureUpdateNeeded(pkg)
@@ -8221,7 +8211,8 @@ Slog.e("TODD",
Slog.w(TAG, "PackageSetting for " + ps.name
+ " is missing signatures. Collecting certs again to recover them.");
} else {
- Slog.i(TAG, toString() + " changed; collecting certs");
+ Slog.i(TAG, pkg.codePath + " changed; collecting certs" +
+ (forceCollect ? " (forced)" : ""));
}
try {
@@ -8320,8 +8311,6 @@ Slog.e("TODD",
return scannedPkg;
}
- // Temporary to catch potential issues with refactoring
- private static boolean REFACTOR_DEBUG = true;
/**
* Adds a new package to the internal data structures during platform initialization.
* <p>After adding, the package is known to the system and available for querying.
@@ -8362,10 +8351,6 @@ Slog.e("TODD",
synchronized (mPackages) {
renamedPkgName = mSettings.getRenamedPackageLPr(pkg.mRealPackage);
final String realPkgName = getRealPackageName(pkg, renamedPkgName);
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "Add pkg: " + pkg.packageName + (realPkgName==null?"":", realName: " + realPkgName));
-}
if (realPkgName != null) {
ensurePackageRenamed(pkg, renamedPkgName);
}
@@ -8380,12 +8365,6 @@ Slog.e("TODD",
if (DEBUG_INSTALL && isSystemPkgUpdated) {
Slog.d(TAG, "updatedPkg = " + disabledPkgSetting);
}
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "SSP? " + scanSystemPartition
- + ", exists? " + pkgAlreadyExists + (pkgAlreadyExists?" "+pkgSetting.toString():"")
- + ", upgraded? " + isSystemPkgUpdated + (isSystemPkgUpdated?" "+disabledPkgSetting.toString():""));
-}
final SharedUserSetting sharedUserSetting = (pkg.mSharedUserId != null)
? mSettings.getSharedUserLPw(pkg.mSharedUserId,
@@ -8397,12 +8376,6 @@ Slog.e("TODD",
Log.d(TAG, "Shared UserID " + pkg.mSharedUserId
+ " (uid=" + sharedUserSetting.userId + "):"
+ " packages=" + sharedUserSetting.packages);
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "Shared UserID " + pkg.mSharedUserId
- + " (uid=" + sharedUserSetting.userId + "):"
- + " packages=" + sharedUserSetting.packages);
-}
}
if (scanSystemPartition) {
@@ -8411,10 +8384,6 @@ Slog.e("TODD",
// version on /data, cycle through all of its children packages and
// remove children that are no longer defined.
if (isSystemPkgUpdated) {
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "Disable child packages");
-}
final int scannedChildCount = (pkg.childPackages != null)
? pkg.childPackages.size() : 0;
final int disabledChildCount = disabledPkgSetting.childPackageNames != null
@@ -8426,19 +8395,11 @@ Slog.e("TODD",
for (int j = 0; j < scannedChildCount; j++) {
PackageParser.Package childPkg = pkg.childPackages.get(j);
if (childPkg.packageName.equals(disabledChildPackageName)) {
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "Ignore " + disabledChildPackageName);
-}
disabledPackageAvailable = true;
break;
}
}
if (!disabledPackageAvailable) {
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "Disable " + disabledChildPackageName);
-}
mSettings.removeDisabledSystemPackageLPw(disabledChildPackageName);
}
}
@@ -8447,44 +8408,17 @@ Slog.e("TODD",
disabledPkgSetting /* pkgSetting */, null /* disabledPkgSetting */,
null /* originalPkgSetting */, null, parseFlags, scanFlags,
(pkg == mPlatformPackage), user);
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "Scan disabled system package");
-Slog.e("TODD",
- "Pre: " + request.pkgSetting.dumpState_temp());
-}
-final ScanResult result =
scanPackageOnlyLI(request, mFactoryTest, -1L);
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "Post: " + (result.success?result.pkgSetting.dumpState_temp():"FAILED scan"));
-}
}
}
}
final boolean newPkgChangedPaths =
pkgAlreadyExists && !pkgSetting.codePathString.equals(pkg.codePath);
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "paths changed? " + newPkgChangedPaths
- + "; old: " + pkg.codePath
- + ", new: " + (pkgSetting==null?"<<NULL>>":pkgSetting.codePathString));
-}
final boolean newPkgVersionGreater =
pkgAlreadyExists && pkg.getLongVersionCode() > pkgSetting.versionCode;
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "version greater? " + newPkgVersionGreater
- + "; old: " + pkg.getLongVersionCode()
- + ", new: " + (pkgSetting==null?"<<NULL>>":pkgSetting.versionCode));
-}
final boolean isSystemPkgBetter = scanSystemPartition && isSystemPkgUpdated
&& newPkgChangedPaths && newPkgVersionGreater;
-if (REFACTOR_DEBUG) {
- Slog.e("TODD",
- "system better? " + isSystemPkgBetter);
-}
if (isSystemPkgBetter) {
// The version of the application on /system is greater than the version on
// /data. Switch back to the application on /system.
@@ -8500,13 +8434,6 @@ if (REFACTOR_DEBUG) {
+ " name: " + pkgSetting.name
+ "; " + pkgSetting.versionCode + " --> " + pkg.getLongVersionCode()
+ "; " + pkgSetting.codePathString + " --> " + pkg.codePath);
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "System package changed;"
- + " name: " + pkgSetting.name
- + "; " + pkgSetting.versionCode + " --> " + pkg.getLongVersionCode()
- + "; " + pkgSetting.codePathString + " --> " + pkg.codePath);
-}
final InstallArgs args = createInstallArgsForExisting(
packageFlagsToInstallFlags(pkgSetting), pkgSetting.codePathString,
@@ -8518,10 +8445,6 @@ Slog.e("TODD",
}
if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) {
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "THROW exception; system pkg version not good enough");
-}
// The version of the application on the /system partition is less than or
// equal to the version on the /data partition. Throw an exception and use
// the application already installed on the /data partition.
@@ -8530,8 +8453,11 @@ Slog.e("TODD",
+ " better than this " + pkg.getLongVersionCode());
}
- // verify certificates against what was last scanned
- collectCertificatesLI(pkgSetting, pkg, parseFlags);
+ // Verify certificates against what was last scanned. If it is an updated priv app, we will
+ // force the verification. Full apk verification will happen unless apk verity is set up for
+ // the file. In that case, only small part of the apk is verified upfront.
+ collectCertificatesLI(pkgSetting, pkg, parseFlags,
+ PackageManagerServiceUtils.isApkVerificationForced(disabledPkgSetting));
boolean shouldHideSystemApp = false;
// A new application appeared on /system, but, we already have a copy of
@@ -8544,11 +8470,6 @@ Slog.e("TODD",
logCriticalInfo(Log.WARN,
"System package signature mismatch;"
+ " name: " + pkgSetting.name);
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "System package signature mismatch;"
- + " name: " + pkgSetting.name);
-}
try (PackageFreezer freezer = freezePackage(pkg.packageName,
"scanPackageInternalLI")) {
deletePackageLIF(pkg.packageName, null, true, null, 0, null, false, null);
@@ -8563,13 +8484,6 @@ Slog.e("TODD",
+ " name: " + pkgSetting.name
+ "; " + pkgSetting.versionCode + " --> " + pkg.getLongVersionCode()
+ "; " + pkgSetting.codePathString + " --> " + pkg.codePath);
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "System package enabled;"
- + " name: " + pkgSetting.name
- + "; " + pkgSetting.versionCode + " --> " + pkg.getLongVersionCode()
- + "; " + pkgSetting.codePathString + " --> " + pkg.codePath);
-}
InstallArgs args = createInstallArgsForExisting(
packageFlagsToInstallFlags(pkgSetting), pkgSetting.codePathString,
pkgSetting.resourcePathString, getAppDexInstructionSets(pkgSetting));
@@ -8586,35 +8500,13 @@ Slog.e("TODD",
+ " name: " + pkgSetting.name
+ "; old: " + pkgSetting.codePathString + " @ " + pkgSetting.versionCode
+ "; new: " + pkg.codePath + " @ " + pkg.codePath);
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "System package disabled;"
- + " name: " + pkgSetting.name
- + "; old: " + pkgSetting.codePathString + " @ " + pkgSetting.versionCode
- + "; new: " + pkg.codePath + " @ " + pkg.codePath);
-}
}
}
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "Scan package");
-Slog.e("TODD",
- "Pre: " + (pkgSetting==null?"<<NONE>>":pkgSetting.dumpState_temp()));
-}
final PackageParser.Package scannedPkg = scanPackageNewLI(pkg, parseFlags, scanFlags
| SCAN_UPDATE_SIGNATURE, currentTime, user);
-if (REFACTOR_DEBUG) {
-pkgSetting = mSettings.getPackageLPr(pkg.packageName);
-Slog.e("TODD",
- "Post: " + (pkgSetting==null?"<<NONE>>":pkgSetting.dumpState_temp()));
-}
if (shouldHideSystemApp) {
-if (REFACTOR_DEBUG) {
-Slog.e("TODD",
- "Disable package: " + pkg.packageName);
-}
synchronized (mPackages) {
mSettings.disableSystemPackageLPw(pkg.packageName, true);
}
@@ -9835,6 +9727,7 @@ Slog.e("TODD",
final @ScanFlags int scanFlags = request.scanFlags;
final PackageSetting oldPkgSetting = request.oldPkgSetting;
final PackageSetting originalPkgSetting = request.originalPkgSetting;
+ final PackageSetting disabledPkgSetting = request.disabledPkgSetting;
final UserHandle user = request.user;
final String realPkgName = request.realPkgName;
final PackageSetting pkgSetting = result.pkgSetting;
@@ -9917,7 +9810,7 @@ Slog.e("TODD",
try {
final boolean compareCompat = isCompatSignatureUpdateNeeded(pkg);
final boolean compareRecover = isRecoverSignatureUpdateNeeded(pkg);
- final boolean compatMatch = verifySignatures(signatureCheckPs,
+ final boolean compatMatch = verifySignatures(signatureCheckPs, disabledPkgSetting,
pkg.mSigningDetails, compareCompat, compareRecover);
// The new KeySets will be re-added later in the scanning process.
if (compatMatch) {
@@ -16687,8 +16580,9 @@ Slog.e("TODD",
try {
final boolean compareCompat = isCompatSignatureUpdateNeeded(pkg);
final boolean compareRecover = isRecoverSignatureUpdateNeeded(pkg);
+ // We don't care about disabledPkgSetting on install for now.
final boolean compatMatch = verifySignatures(
- signatureCheckPs, pkg.mSigningDetails, compareCompat,
+ signatureCheckPs, null, pkg.mSigningDetails, compareCompat,
compareRecover);
// The new KeySets will be re-added later in the scanning process.
if (compatMatch) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index df836de21a80..7b96ca67d38f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -33,10 +33,12 @@ import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.PackageDexUsage;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.AppGlobals;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.os.Build;
@@ -45,6 +47,7 @@ import android.os.Environment;
import android.os.FileUtils;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.service.pm.PackageServiceDumpProto;
import android.system.ErrnoException;
@@ -547,13 +550,46 @@ public class PackageManagerServiceUtils {
}
/**
+ * Make sure the updated priv app is signed with the same key as the original APK file on the
+ * /system partition.
+ *
+ * <p>The rationale is that {@code disabledPkg} is a PackageSetting backed by xml files in /data
+ * and is not tamperproof.
+ */
+ private static boolean matchSignatureInSystem(PackageSetting pkgSetting,
+ PackageSetting disabledPkgSetting) {
+ try {
+ PackageParser.collectCertificates(disabledPkgSetting.pkg,
+ PackageParser.PARSE_IS_SYSTEM_DIR);
+ if (compareSignatures(pkgSetting.signatures.mSignatures,
+ disabledPkgSetting.signatures.mSignatures)
+ != PackageManager.SIGNATURE_MATCH) {
+ logCriticalInfo(Log.ERROR, "Updated system app mismatches cert on /system: " +
+ pkgSetting.name);
+ return false;
+ }
+ } catch (PackageParserException e) {
+ logCriticalInfo(Log.ERROR, "Failed to collect cert for " + pkgSetting.name + ": " +
+ e.getMessage());
+ return false;
+ }
+ return true;
+ }
+
+ /** Returns true to force apk verification if the updated package (in /data) is a priv app. */
+ static boolean isApkVerificationForced(@Nullable PackageSetting disabledPs) {
+ return disabledPs != null && disabledPs.isPrivileged() &&
+ SystemProperties.getInt("ro.apk_verity.mode", 0) != 0;
+ }
+
+ /**
* Verifies that signatures match.
* @returns {@code true} if the compat signatures were matched; otherwise, {@code false}.
* @throws PackageManagerException if the signatures did not match.
*/
public static boolean verifySignatures(PackageSetting pkgSetting,
- PackageParser.SigningDetails parsedSignatures, boolean compareCompat,
- boolean compareRecover)
+ PackageSetting disabledPkgSetting, PackageParser.SigningDetails parsedSignatures,
+ boolean compareCompat, boolean compareRecover)
throws PackageManagerException {
final String packageName = pkgSetting.name;
boolean compatMatch = false;
@@ -572,6 +608,11 @@ public class PackageManagerServiceUtils {
packageName, pkgSetting.signatures.mSignatures,
parsedSignatures.signatures);
}
+
+ if (!match && isApkVerificationForced(disabledPkgSetting)) {
+ match = matchSignatureInSystem(pkgSetting, disabledPkgSetting);
+ }
+
if (!match) {
throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
"Package " + packageName +
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 0d7ef663fa07..2b91b7d38b4f 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -97,35 +97,6 @@ public final class PackageSetting extends PackageSettingBase {
+ " " + name + "/" + appId + "}";
}
- // Temporary to catch potential issues with refactoring
- public String dumpState_temp() {
- String flags = "";
- flags += ((pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 ? "U" : "");
- flags += ((pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0 ? "S" : "");
- if ("".equals(flags)) {
- flags = "-";
- }
- String privFlags = "";
- privFlags += ((pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0 ? "P" : "");
- privFlags += ((pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0 ? "O" : "");
- privFlags += ((pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0 ? "V" : "");
- if ("".equals(privFlags)) {
- privFlags = "-";
- }
- return "PackageSetting{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + name + (realName == null ? "" : "("+realName+")") + "/" + appId + (sharedUser==null?"":" u:" + sharedUser.name+"("+sharedUserId+")")
- + ", ver:" + versionCode
- + ", path: " + codePath
- + ", pABI: " + primaryCpuAbiString
- + ", sABI: " + secondaryCpuAbiString
- + ", oABI: " + cpuAbiOverrideString
- + ", flags: " + flags
- + ", privFlags: " + privFlags
- + ", pkg: " + (pkg == null ? "<<NULL>>" : "{" + Integer.toHexString(System.identityHashCode(pkg)) + "}")
- + "}";
- }
-
public void copyFrom(PackageSetting orig) {
super.copyFrom(orig);
doCopy(orig);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 7d575668da94..92fd9041b32d 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -394,7 +394,7 @@ public class UserManagerService extends IUserManager.Stub {
/**
* Start an {@link IntentSender} when user is unlocked after disabling quiet mode.
*
- * @see {@link #trySetQuietModeEnabled(String, boolean, int, IntentSender)}
+ * @see {@link #requestQuietModeEnabled(String, boolean, int, IntentSender)}
*/
private class DisableQuietModeUserUnlockedCallback extends IProgressListener.Stub {
private final IntentSender mTarget;
@@ -823,7 +823,7 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
- public boolean trySetQuietModeEnabled(@NonNull String callingPackage, boolean enableQuietMode,
+ public boolean requestQuietModeEnabled(@NonNull String callingPackage, boolean enableQuietMode,
int userHandle, @Nullable IntentSender target) {
Preconditions.checkNotNull(callingPackage);
diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java
index 6f005a35a28c..a538967e501d 100644
--- a/services/core/java/com/android/server/power/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
+import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerSaveState;
import android.provider.Settings;
@@ -49,21 +50,6 @@ public class BatterySaverPolicy extends ContentObserver {
public static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE.
- /** Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode. */
- public static final int GPS_MODE_NO_CHANGE = 0;
-
- /**
- * Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
- * is enabled and the screen is off.
- */
- public static final int GPS_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
-
- /**
- * Value of batterySaverGpsMode such that location should be disabled altogether
- * when battery saver mode is enabled and the screen is off.
- */
- public static final int GPS_MODE_ALL_DISABLED_WHEN_SCREEN_OFF = 2;
-
// Secure setting for GPS behavior when battery saver mode is on.
public static final String SECURE_KEY_GPS_MODE = "batterySaverGpsMode";
@@ -354,7 +340,7 @@ public class BatterySaverPolicy extends ContentObserver {
// Get default value from Settings.Secure
final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE,
- GPS_MODE_ALL_DISABLED_WHEN_SCREEN_OFF);
+ PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF);
mGpsMode = parser.getInt(KEY_GPS_MODE, defaultGpsMode);
// Non-device-specific parameters.
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverLocationPlugin.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverLocationPlugin.java
index 0af19b6f2c5d..bd8baeb8f778 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverLocationPlugin.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverLocationPlugin.java
@@ -16,11 +16,11 @@
package com.android.server.power.batterysaver;
import android.content.Context;
+import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.util.Slog;
-import com.android.server.power.BatterySaverPolicy;
import com.android.server.power.batterysaver.BatterySaverController.Plugin;
public class BatterySaverLocationPlugin implements Plugin {
@@ -53,7 +53,7 @@ public class BatterySaverLocationPlugin implements Plugin {
private void updateLocationState(BatterySaverController caller) {
final boolean kill =
(caller.getBatterySaverPolicy().getGpsMode()
- == BatterySaverPolicy.GPS_MODE_ALL_DISABLED_WHEN_SCREEN_OFF) &&
+ == PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF) &&
caller.isEnabled() && !caller.isInteractive();
if (DEBUG) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 0c7397afb879..c532a8a25bda 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -107,6 +107,68 @@ public class ZenModeHelperTest extends UiServiceTestCase {
}
@Test
+ public void testAlarmsOnly_alarmMediaMuteNotApplied() {
+ mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
+ mZenModeHelperSpy.mConfig.allowAlarms = false;
+ mZenModeHelperSpy.mConfig.allowMediaSystemOther = false;
+ assertFalse(mZenModeHelperSpy.mConfig.allowAlarms);
+ assertFalse(mZenModeHelperSpy.mConfig.allowMediaSystemOther);
+ mZenModeHelperSpy.applyRestrictions();
+
+ // Alarms only mode will not silence alarms
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ AudioAttributes.USAGE_ALARM);
+
+ // Alarms only mode will not silence media
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ AudioAttributes.USAGE_MEDIA);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ AudioAttributes.USAGE_GAME);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ AudioAttributes.USAGE_ASSISTANCE_SONIFICATION);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ AudioAttributes.USAGE_UNKNOWN);
+ }
+
+ @Test
+ public void testAlarmsOnly_callsMuteApplied() {
+ mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
+ mZenModeHelperSpy.mConfig.allowCalls = true;
+ assertTrue(mZenModeHelperSpy.mConfig.allowCalls);
+ mZenModeHelperSpy.applyRestrictions();
+
+ // Alarms only mode will silence calls despite priority-mode config
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST);
+ }
+
+ @Test
+ public void testAlarmsOnly_allZenConfigToggledCannotBypass_alarmMuteNotApplied() {
+ // Only audio attributes with SUPPRESIBLE_NEVER can bypass
+ mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
+ mZenModeHelperSpy.mConfig.allowAlarms = false;
+ mZenModeHelperSpy.mConfig.allowMediaSystemOther = false;
+ mZenModeHelperSpy.mConfig.allowReminders = false;
+ mZenModeHelperSpy.mConfig.allowCalls = false;
+ mZenModeHelperSpy.mConfig.allowMessages = false;
+ mZenModeHelperSpy.mConfig.allowEvents = false;
+ mZenModeHelperSpy.mConfig.allowRepeatCallers= false;
+ assertFalse(mZenModeHelperSpy.mConfig.allowAlarms);
+ assertFalse(mZenModeHelperSpy.mConfig.allowMediaSystemOther);
+ assertFalse(mZenModeHelperSpy.mConfig.allowReminders);
+ assertFalse(mZenModeHelperSpy.mConfig.allowCalls);
+ assertFalse(mZenModeHelperSpy.mConfig.allowMessages);
+ assertFalse(mZenModeHelperSpy.mConfig.allowEvents);
+ assertFalse(mZenModeHelperSpy.mConfig.allowRepeatCallers);
+ mZenModeHelperSpy.applyRestrictions();
+
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ AudioAttributes.USAGE_ALARM);
+ }
+
+ @Test
public void testZenAllCannotBypass() {
// Only audio attributes with SUPPRESIBLE_NEVER can bypass
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
diff --git a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
index 8ed96a3a4f36..7eeb1ce7991c 100644
--- a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
+++ b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
@@ -15,12 +15,10 @@
*/
package android.telephony;
-import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
-
-import android.telecom.PhoneAccountHandle;
import android.telephony.VisualVoicemailService.VisualVoicemailTask;
+
import java.util.Collections;
import java.util.List;
@@ -75,6 +73,7 @@ public final class VisualVoicemailSmsFilterSettings implements Parcelable {
private String mClientPrefix = DEFAULT_CLIENT_PREFIX;
private List<String> mOriginatingNumbers = DEFAULT_ORIGINATING_NUMBERS;
private int mDestinationPort = DEFAULT_DESTINATION_PORT;
+ private String mPackageName;
public VisualVoicemailSmsFilterSettings build() {
return new VisualVoicemailSmsFilterSettings(this);
@@ -116,6 +115,15 @@ public final class VisualVoicemailSmsFilterSettings implements Parcelable {
return this;
}
+ /**
+ * The package that registered this filter.
+ *
+ * @hide
+ */
+ public Builder setPackageName(String packageName) {
+ mPackageName = packageName;
+ return this;
+ }
}
/**
@@ -138,12 +146,20 @@ public final class VisualVoicemailSmsFilterSettings implements Parcelable {
public final int destinationPort;
/**
+ * The package that registered this filter.
+ *
+ * @hide
+ */
+ public final String packageName;
+
+ /**
* Use {@link Builder} to construct
*/
private VisualVoicemailSmsFilterSettings(Builder builder) {
clientPrefix = builder.mClientPrefix;
originatingNumbers = builder.mOriginatingNumbers;
destinationPort = builder.mDestinationPort;
+ packageName = builder.mPackageName;
}
public static final Creator<VisualVoicemailSmsFilterSettings> CREATOR =
@@ -154,7 +170,7 @@ public final class VisualVoicemailSmsFilterSettings implements Parcelable {
builder.setClientPrefix(in.readString());
builder.setOriginatingNumbers(in.createStringArrayList());
builder.setDestinationPort(in.readInt());
-
+ builder.setPackageName(in.readString());
return builder.build();
}
@@ -174,10 +190,11 @@ public final class VisualVoicemailSmsFilterSettings implements Parcelable {
dest.writeString(clientPrefix);
dest.writeStringList(originatingNumbers);
dest.writeInt(destinationPort);
+ dest.writeString(packageName);
}
@Override
- public String toString(){
+ public String toString() {
return "[VisualVoicemailSmsFilterSettings "
+ "clientPrefix=" + clientPrefix
+ ", originatingNumbers=" + originatingNumbers
diff --git a/telephony/java/android/telephony/euicc/EuiccNotification.java b/telephony/java/android/telephony/euicc/EuiccNotification.java
new file mode 100644
index 000000000000..ef3c1ce8cf3b
--- /dev/null
+++ b/telephony/java/android/telephony/euicc/EuiccNotification.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony.euicc;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * This represents a signed notification which is defined in SGP.22. It can be either a profile
+ * installation result or a notification generated for profile operations (e.g., enabling,
+ * disabling, or deleting).
+ *
+ * @hide
+ *
+ * TODO(b/35851809): Make this a @SystemApi.
+ */
+public class EuiccNotification implements Parcelable {
+ /** Event */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "EVENT_" }, value = {
+ EVENT_INSTALL,
+ EVENT_ENABLE,
+ EVENT_DISABLE,
+ EVENT_DELETE
+ })
+ public @interface Event {}
+
+ /** A profile is downloaded and installed. */
+ public static final int EVENT_INSTALL = 1;
+
+ /** A profile is enabled. */
+ public static final int EVENT_ENABLE = 1 << 1;
+
+ /** A profile is disabled. */
+ public static final int EVENT_DISABLE = 1 << 2;
+
+ /** A profile is deleted. */
+ public static final int EVENT_DELETE = 1 << 3;
+
+ /** Value of the bits of all above events */
+ @Event
+ public static final int ALL_EVENTS =
+ EVENT_INSTALL | EVENT_ENABLE | EVENT_DISABLE | EVENT_DELETE;
+
+ private final int mSeq;
+ private final String mTargetAddr;
+ @Event private final int mEvent;
+ @Nullable private final byte[] mData;
+
+ /**
+ * Creates an instance.
+ *
+ * @param seq The sequence number of this notification.
+ * @param targetAddr The target server where to send this notification.
+ * @param event The event which causes this notification.
+ * @param data The data which needs to be sent to the target server. This can be null for
+ * building a list of notification metadata without data.
+ */
+ public EuiccNotification(int seq, String targetAddr, @Event int event, @Nullable byte[] data) {
+ mSeq = seq;
+ mTargetAddr = targetAddr;
+ mEvent = event;
+ mData = data;
+ }
+
+ /** @return The sequence number of this notification. */
+ public int getSeq() {
+ return mSeq;
+ }
+
+ /** @return The target server address where this notification should be sent to. */
+ public String getTargetAddr() {
+ return mTargetAddr;
+ }
+
+ /** @return The event of this notification. */
+ @Event
+ public int getEvent() {
+ return mEvent;
+ }
+
+ /** @return The notification data which needs to be sent to the target server. */
+ @Nullable
+ public byte[] getData() {
+ return mData;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ EuiccNotification that = (EuiccNotification) obj;
+ return mSeq == that.mSeq
+ && Objects.equals(mTargetAddr, that.mTargetAddr)
+ && mEvent == that.mEvent
+ && Arrays.equals(mData, that.mData);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + mSeq;
+ result = 31 * result + Objects.hashCode(mTargetAddr);
+ result = 31 * result + mEvent;
+ result = 31 * result + Arrays.hashCode(mData);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "EuiccNotification (seq="
+ + mSeq
+ + ", targetAddr="
+ + mTargetAddr
+ + ", event="
+ + mEvent
+ + ", data="
+ + (mData == null ? "null" : "byte[" + mData.length + "]")
+ + ")";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mSeq);
+ dest.writeString(mTargetAddr);
+ dest.writeInt(mEvent);
+ dest.writeByteArray(mData);
+ }
+
+ private EuiccNotification(Parcel source) {
+ mSeq = source.readInt();
+ mTargetAddr = source.readString();
+ mEvent = source.readInt();
+ mData = source.createByteArray();
+ }
+
+ public static final Creator<EuiccNotification> CREATOR =
+ new Creator<EuiccNotification>() {
+ @Override
+ public EuiccNotification createFromParcel(Parcel source) {
+ return new EuiccNotification(source);
+ }
+
+ @Override
+ public EuiccNotification[] newArray(int size) {
+ return new EuiccNotification[size];
+ }
+ };
+}
diff --git a/telephony/java/android/telephony/euicc/EuiccRat.java b/telephony/java/android/telephony/euicc/EuiccRat.java
new file mode 100644
index 000000000000..6a56503ac380
--- /dev/null
+++ b/telephony/java/android/telephony/euicc/EuiccRat.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony.euicc;
+
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.service.carrier.CarrierIdentifier;
+import android.service.euicc.EuiccProfileInfo;
+import android.text.TextUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+
+/**
+ * This represents the RAT (Rules Authorisation Table) stored on eUICC.
+ *
+ * @hide
+ *
+ * TODO(b/35851809): Make this a @SystemApi.
+ */
+public final class EuiccRat implements Parcelable {
+ /** Profile policy rule flags */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "POLICY_RULE_FLAG_" }, value = {
+ POLICY_RULE_FLAG_CONSENT_REQUIRED
+ })
+ public @interface PolicyRuleFlag {}
+
+ /** User consent is required to install the profile. */
+ public static final int POLICY_RULE_FLAG_CONSENT_REQUIRED = 1;
+
+ private final int[] mPolicyRules;
+ private final CarrierIdentifier[][] mCarrierIds;
+ private final int[] mPolicyRuleFlags;
+
+ /** This is used to build new {@link EuiccRat} instance. */
+ public static final class Builder {
+ private int[] mPolicyRules;
+ private CarrierIdentifier[][] mCarrierIds;
+ private int[] mPolicyRuleFlags;
+ private int mPosition;
+
+ /**
+ * Creates a new builder.
+ *
+ * @param ruleNum The number of authorisation rules in the table.
+ */
+ public Builder(int ruleNum) {
+ mPolicyRules = new int[ruleNum];
+ mCarrierIds = new CarrierIdentifier[ruleNum][];
+ mPolicyRuleFlags = new int[ruleNum];
+ }
+
+ /**
+ * Builds the RAT instance. This builder should not be used anymore after this method is
+ * called, otherwise {@link NullPointerException} will be thrown.
+ */
+ public EuiccRat build() {
+ if (mPosition != mPolicyRules.length) {
+ throw new IllegalStateException(
+ "Not enough rules are added, expected: "
+ + mPolicyRules.length
+ + ", added: "
+ + mPosition);
+ }
+ return new EuiccRat(mPolicyRules, mCarrierIds, mPolicyRuleFlags);
+ }
+
+ /**
+ * Adds an authorisation rule.
+ *
+ * @throws ArrayIndexOutOfBoundsException If the {@code mPosition} is larger than the size
+ * this table.
+ */
+ public Builder add(int policyRules, CarrierIdentifier[] carrierId, int policyRuleFlags) {
+ if (mPosition >= mPolicyRules.length) {
+ throw new ArrayIndexOutOfBoundsException(mPosition);
+ }
+ mPolicyRules[mPosition] = policyRules;
+ mCarrierIds[mPosition] = carrierId;
+ mPolicyRuleFlags[mPosition] = policyRuleFlags;
+ mPosition++;
+ return this;
+ }
+ }
+
+ /**
+ * @param mccRule A 2-character or 3-character string which can be either MCC or MNC. The
+ * character 'E' is used as a wild char to match any digit.
+ * @param mcc A 2-character or 3-character string which can be either MCC or MNC.
+ * @return Whether the {@code mccRule} matches {@code mcc}.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public static boolean match(String mccRule, String mcc) {
+ if (mccRule.length() < mcc.length()) {
+ return false;
+ }
+ for (int i = 0; i < mccRule.length(); i++) {
+ // 'E' is the wild char to match any digit.
+ if (mccRule.charAt(i) == 'E'
+ || (i < mcc.length() && mccRule.charAt(i) == mcc.charAt(i))) {
+ continue;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ private EuiccRat(int[] policyRules, CarrierIdentifier[][] carrierIds, int[] policyRuleFlags) {
+ mPolicyRules = policyRules;
+ mCarrierIds = carrierIds;
+ mPolicyRuleFlags = policyRuleFlags;
+ }
+
+ /**
+ * Finds the index of the first authorisation rule matching the given policy and carrier id. If
+ * the returned index is not negative, the carrier is allowed to apply this policy to its
+ * profile.
+ *
+ * @param policy The policy rule.
+ * @param carrierId The carrier id.
+ * @return The index of authorization rule. If no rule is found, -1 will be returned.
+ */
+ public int findIndex(@EuiccProfileInfo.PolicyRule int policy, CarrierIdentifier carrierId) {
+ for (int i = 0; i < mPolicyRules.length; i++) {
+ if ((mPolicyRules[i] & policy) == 0) {
+ continue;
+ }
+ CarrierIdentifier[] carrierIds = mCarrierIds[i];
+ if (carrierIds == null || carrierIds.length == 0) {
+ continue;
+ }
+ for (int j = 0; j < carrierIds.length; j++) {
+ CarrierIdentifier ruleCarrierId = carrierIds[j];
+ if (!match(ruleCarrierId.getMcc(), carrierId.getMcc())
+ || !match(ruleCarrierId.getMnc(), carrierId.getMnc())) {
+ continue;
+ }
+ String gid = ruleCarrierId.getGid1();
+ if (!TextUtils.isEmpty(gid) && !gid.equals(carrierId.getGid1())) {
+ continue;
+ }
+ gid = ruleCarrierId.getGid2();
+ if (!TextUtils.isEmpty(gid) && !gid.equals(carrierId.getGid2())) {
+ continue;
+ }
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Tests if the entry in the table has the given policy rule flag.
+ *
+ * @param index The index of the entry.
+ * @param flag The policy rule flag to be tested.
+ * @throws ArrayIndexOutOfBoundsException If the {@code index} is negative or larger than the
+ * size of this table.
+ */
+ public boolean hasPolicyRuleFlag(int index, @PolicyRuleFlag int flag) {
+ if (index < 0 || index >= mPolicyRules.length) {
+ throw new ArrayIndexOutOfBoundsException(index);
+ }
+ return (mPolicyRuleFlags[index] & flag) != 0;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeIntArray(mPolicyRules);
+ for (CarrierIdentifier[] ids : mCarrierIds) {
+ dest.writeTypedArray(ids, flags);
+ }
+ dest.writeIntArray(mPolicyRuleFlags);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ EuiccRat that = (EuiccRat) obj;
+ if (mCarrierIds.length != that.mCarrierIds.length) {
+ return false;
+ }
+ for (int i = 0; i < mCarrierIds.length; i++) {
+ CarrierIdentifier[] carrierIds = mCarrierIds[i];
+ CarrierIdentifier[] thatCarrierIds = that.mCarrierIds[i];
+ if (carrierIds != null && thatCarrierIds != null) {
+ if (carrierIds.length != thatCarrierIds.length) {
+ return false;
+ }
+ for (int j = 0; j < carrierIds.length; j++) {
+ if (!carrierIds[j].equals(thatCarrierIds[j])) {
+ return false;
+ }
+ }
+ continue;
+ } else if (carrierIds == null && thatCarrierIds == null) {
+ continue;
+ }
+ return false;
+ }
+
+ return Arrays.equals(mPolicyRules, that.mPolicyRules)
+ && Arrays.equals(mPolicyRuleFlags, that.mPolicyRuleFlags);
+ }
+
+ private EuiccRat(Parcel source) {
+ mPolicyRules = source.createIntArray();
+ int len = mPolicyRules.length;
+ mCarrierIds = new CarrierIdentifier[len][];
+ for (int i = 0; i < len; i++) {
+ mCarrierIds[i] = source.createTypedArray(CarrierIdentifier.CREATOR);
+ }
+ mPolicyRuleFlags = source.createIntArray();
+ }
+
+ public static final Creator<EuiccRat> CREATOR =
+ new Creator<EuiccRat>() {
+ @Override
+ public EuiccRat createFromParcel(Parcel source) {
+ return new EuiccRat(source);
+ }
+
+ @Override
+ public EuiccRat[] newArray(int size) {
+ return new EuiccRat[size];
+ }
+ };
+}
diff --git a/telephony/java/com/android/ims/ImsCallProfile.java b/telephony/java/com/android/ims/ImsCallProfile.java
index 489c208a0d46..693aaff8ce0f 100644
--- a/telephony/java/com/android/ims/ImsCallProfile.java
+++ b/telephony/java/com/android/ims/ImsCallProfile.java
@@ -351,7 +351,7 @@ public class ImsCallProfile implements Parcelable {
mServiceType = in.readInt();
mCallType = in.readInt();
mCallExtras = in.readBundle();
- mMediaProfile = in.readParcelable(null);
+ mMediaProfile = in.readParcelable(ImsStreamMediaProfile.class.getClassLoader());
}
public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() {
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index 3bec082fc57a..101f74eafaf4 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -772,8 +772,8 @@ int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) {
if (*type != ResourceType::kRaw) {
if (path_data.extension == "xml") {
compile_func = &CompileXml;
- } else if (!options.no_png_crunch &&
- (path_data.extension == "png" || path_data.extension == "9.png")) {
+ } else if ((!options.no_png_crunch && path_data.extension == "png") ||
+ path_data.extension == "9.png") {
compile_func = &CompilePng;
}
}
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 421e54558df4..399b0c63e113 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -100,9 +100,11 @@ class Method():
self.typ = raw[0]
self.name = raw[1]
self.args = []
+ self.throws = []
+ target = self.args
for r in raw[2:]:
- if r == "throws": break
- self.args.append(r)
+ if r == "throws": target = self.throws
+ else: target.append(r)
# identity for compat purposes
ident = self.raw
@@ -391,7 +393,7 @@ def verify_actions(clazz):
prefix = clazz.pkg.name + ".action"
expected = prefix + "." + f.name[7:]
if f.value != expected:
- error(clazz, f, "C4", "Inconsistent action value; expected %s" % (expected))
+ error(clazz, f, "C4", "Inconsistent action value; expected '%s'" % (expected))
def verify_extras(clazz):
@@ -421,7 +423,7 @@ def verify_extras(clazz):
prefix = clazz.pkg.name + ".extra"
expected = prefix + "." + f.name[6:]
if f.value != expected:
- error(clazz, f, "C4", "Inconsistent extra value; expected %s" % (expected))
+ error(clazz, f, "C4", "Inconsistent extra value; expected '%s'" % (expected))
def verify_equals(clazz):
@@ -450,6 +452,10 @@ def verify_parcelable(clazz):
(" final deprecated class " not in clazz.raw)):
error(clazz, None, "FW8", "Parcelable classes must be final")
+ for c in clazz.ctors:
+ if c.args == ["android.os.Parcel"]:
+ error(clazz, c, "FW3", "Parcelable inflation is exposed through CREATOR, not raw constructors")
+
def verify_protected(clazz):
"""Verify that no protected methods or fields are allowed."""
@@ -572,7 +578,7 @@ def verify_helper_classes(clazz):
if f.name == "SERVICE_INTERFACE":
found = True
if f.value != clazz.fullname:
- error(clazz, f, "C4", "Inconsistent interface constant; expected %s" % (clazz.fullname))
+ error(clazz, f, "C4", "Inconsistent interface constant; expected '%s'" % (clazz.fullname))
if "extends android.content.ContentProvider" in clazz.raw:
test_methods = True
@@ -584,7 +590,7 @@ def verify_helper_classes(clazz):
if f.name == "PROVIDER_INTERFACE":
found = True
if f.value != clazz.fullname:
- error(clazz, f, "C4", "Inconsistent interface constant; expected %s" % (clazz.fullname))
+ error(clazz, f, "C4", "Inconsistent interface constant; expected '%s'" % (clazz.fullname))
if "extends android.content.BroadcastReceiver" in clazz.raw:
test_methods = True
@@ -764,15 +770,19 @@ def verify_flags(clazz):
def verify_exception(clazz):
"""Verifies that methods don't throw generic exceptions."""
for m in clazz.methods:
- if "throws java.lang.Exception" in m.raw or "throws java.lang.Throwable" in m.raw or "throws java.lang.Error" in m.raw:
- error(clazz, m, "S1", "Methods must not throw generic exceptions")
+ for t in m.throws:
+ if t in ["java.lang.Exception", "java.lang.Throwable", "java.lang.Error"]:
+ error(clazz, m, "S1", "Methods must not throw generic exceptions")
+
+ if t in ["android.os.RemoteException"]:
+ if clazz.name == "android.content.ContentProviderClient": continue
+ if clazz.name == "android.os.Binder": continue
+ if clazz.name == "android.os.IBinder": continue
- if "throws android.os.RemoteException" in m.raw:
- if clazz.name == "android.content.ContentProviderClient": continue
- if clazz.name == "android.os.Binder": continue
- if clazz.name == "android.os.IBinder": continue
+ error(clazz, m, "FW9", "Methods calling into system server should rethrow RemoteException as RuntimeException")
- error(clazz, m, "FW9", "Methods calling into system server should rethrow RemoteException as RuntimeException")
+ if len(m.args) == 0 and t in ["java.lang.IllegalArgumentException", "java.lang.NullPointerException"]:
+ warn(clazz, m, "S1", "Methods taking no arguments should throw IllegalStateException")
def verify_google(clazz):
@@ -927,7 +937,8 @@ def verify_callback_handlers(clazz):
found = {}
by_name = collections.defaultdict(list)
- for m in clazz.methods:
+ examine = clazz.ctors + clazz.methods
+ for m in examine:
if m.name.startswith("unregister"): continue
if m.name.startswith("remove"): continue
if re.match("on[A-Z]+", m.name): continue
@@ -971,7 +982,7 @@ def verify_listener_last(clazz):
for a in m.args:
if a.endswith("Callback") or a.endswith("Callbacks") or a.endswith("Listener"):
found = True
- elif found and a != "android.os.Handler" and a != "java.util.concurrent.Executor":
+ elif found:
warn(clazz, m, "M3", "Listeners should always be at end of argument list")
@@ -1078,16 +1089,11 @@ def verify_runtime_exceptions(clazz):
"java.nio.BufferOverflowException",
]
- test = []
- test.extend(clazz.ctors)
- test.extend(clazz.methods)
-
- for t in test:
- if " throws " not in t.raw: continue
- throws = t.raw[t.raw.index(" throws "):]
- for b in banned:
- if b in throws:
- error(clazz, t, None, "Methods must not mention RuntimeException subclasses in throws clauses")
+ examine = clazz.ctors + clazz.methods
+ for m in examine:
+ for t in m.throws:
+ if t in banned:
+ error(clazz, m, None, "Methods must not mention RuntimeException subclasses in throws clauses")
def verify_error(clazz):
@@ -1233,6 +1239,58 @@ def verify_collections_over_arrays(clazz):
warn(clazz, m, None, "Method argument should be Collection<> (or subclass) instead of raw array")
+def verify_user_handle(clazz):
+ """Methods taking UserHandle should be ForUser or AsUser."""
+ if clazz.name.endswith("Listener") or clazz.name.endswith("Callback") or clazz.name.endswith("Callbacks"): return
+ if clazz.fullname == "android.app.admin.DeviceAdminReceiver": return
+ if clazz.fullname == "android.content.pm.LauncherApps": return
+ if clazz.fullname == "android.os.UserHandle": return
+ if clazz.fullname == "android.os.UserManager": return
+
+ for m in clazz.methods:
+ if m.name.endswith("AsUser") or m.name.endswith("ForUser"): continue
+ if re.match("on[A-Z]+", m.name): continue
+ if "android.os.UserHandle" in m.args:
+ warn(clazz, m, None, "Method taking UserHandle should be named 'doFooAsUser' or 'queryFooForUser'")
+
+
+def verify_params(clazz):
+ """Parameter classes should be 'Params'."""
+ if clazz.name.endswith("Params"): return
+ if clazz.fullname == "android.app.ActivityOptions": return
+ if clazz.fullname == "android.app.BroadcastOptions": return
+ if clazz.fullname == "android.os.Bundle": return
+ if clazz.fullname == "android.os.BaseBundle": return
+ if clazz.fullname == "android.os.PersistableBundle": return
+
+ bad = ["Param","Parameter","Parameters","Args","Arg","Argument","Arguments","Options","Bundle"]
+ for b in bad:
+ if clazz.name.endswith(b):
+ error(clazz, None, None, "Classes holding a set of parameters should be called 'FooParams'")
+
+
+def verify_services(clazz):
+ """Service name should be FOO_BAR_SERVICE = 'foo_bar'."""
+ if clazz.fullname != "android.content.Context": return
+
+ for f in clazz.fields:
+ if f.typ != "java.lang.String": continue
+ found = re.match(r"([A-Z_]+)_SERVICE", f.name)
+ if found:
+ expected = found.group(1).lower()
+ if f.value != expected:
+ error(clazz, f, "C4", "Inconsistent service value; expected '%s'" % (expected))
+
+
+def verify_tense(clazz):
+ """Verify tenses of method names."""
+ if clazz.fullname.startswith("android.opengl"): return
+
+ for m in clazz.methods:
+ if m.name.endswith("Enable"):
+ warn(clazz, m, None, "Unexpected tense; probably meant 'enabled'")
+
+
def examine_clazz(clazz):
"""Find all style issues in the given class."""
@@ -1290,6 +1348,10 @@ def examine_clazz(clazz):
verify_member_name_not_kotlin_keyword(clazz)
verify_method_name_not_kotlin_operator(clazz)
verify_collections_over_arrays(clazz)
+ verify_user_handle(clazz)
+ verify_params(clazz)
+ verify_services(clazz)
+ verify_tense(clazz)
def examine_stream(stream):